AcWing 890. 能被整除的數
阿新 • • 發佈:2022-03-05
目錄
題目描述
給定一個整數 nn 和 mm 個不同的質數 p1,p2,…,pmp1,p2,…,pm。
請你求出 1∼n1∼n 中能被 p1,p2,…,pmp1,p2,…,pm 中的至少一個數整除的整數有多少個。
輸入格式
第一行包含整數 nn 和 mm。
第二行包含 mm 個質數。
輸出格式
輸出一個整數,表示滿足條件的整數的個數。
資料範圍
1≤m≤161≤m≤16,
1≤n,pi≤1091≤n,pi≤109輸入樣例:
10 2 2 3
輸出樣例:
7
演算法求解
分析
這個題目是容斥原理的公式
用p[i]
表示讀入的質數
用\(S_i\) 表示在1--n
內能被 p[i]
整除的數的集合
程式碼
#include<iostream> #include<cstdio> using namespace std; typedef long long LL; const int N = 20; int p[N]; int n, m; int main() { scanf("%d%d", &n, &m); for(int i = 0; i < m; i++) scanf("%d", &p[i]); LL res = 0; for(int i = 1; i < 1 << m; i++) { int cnt = 0; int t = 1; for(int j = 0; j < m; j++) { // 如果選中了這個集合 if((i >> j) & 1) { if((LL)t*p[j] > n) { t = -1; break; } cnt++; t *= p[j]; // 能被選中集合的交集整除的是該集合內質數的乘積 } if(t == -1) continue; if(cnt & 1) res += n/t; else res -= n/t; } } cout << res << endl; return 0; /* 暴力 scanf("%d%d", &n, &m); for(int i = 0; i < m; i++) scanf("%d", &a[i]); int res = 0; for(int i = 1; i <= n; i++) { for(int j = 0; j < m; j++) if(i % a[j] == 0) { res ++; break; } } cout << res << endl; return 0;*/ }
時間複雜度
\(O(2^m * m)\)