spoj 4168. Square-free integers(容斥)
阿新 • • 發佈:2018-12-30
求出1~n(n <= 10^14)內不被任意一個完全平方數整除的數的個數。
同樣的,考慮問題的逆問題,就是至少能被一個完全平方數整除的數的個數。所以答案就是 n - ( 1~n內完全平方數的倍數的個數 )。
所以可以列舉i( 2 <= i <= sqrt(n) ),i*i是一個完全平方數,那麼能被i*i整除的數的個數為 n / (i*i)。顯然裡面有重複的,例如4,9,和36,
36就被多計算的一次,所以減掉,就是容斥。 和上題類似,看i的質因子數是奇數還是偶數,是奇數就加上,偶數就減掉,注意i的質因子不能有重複的。
每個數的質因子個數我們可以提前dfs預處理出來。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <bitset> #include <list> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> //#define LL __int64 //#define LL long long #define eps 1e-9 #define PI acos(-1.0) typedef long long LL; using namespace std; const int maxn = 10000010; int cnt[maxn]; bool flag[maxn]; int prime[maxn]; int p_num; void getPrime() { int m = sqrt(maxn); memset(flag,false,sizeof(flag)); p_num = 0; for(int i = 2; i <= m; i++) { if(flag[i] == false) { for(int j = i+i; j <= maxn; j += i) flag[j] = true; } } for(int i = 2; i < maxn; i++) if(flag[i] == false) prime[p_num++] = i; } void dfs(int st, LL s, int num) { cnt[s] = num&1 ? 1 : -1; for(int i = st; i < p_num; i++) { LL tmp = prime[i] * s; if(tmp > maxn) break; dfs(i+1,tmp,num+1); } } int main() { int test; memset(cnt,0,sizeof(cnt)); getPrime(); dfs(0,1LL,0); scanf("%d",&test); while(test--) { LL n; scanf("%lld",&n); int m = sqrt(n+0.5); LL ans = 0; for(int i = 2; i <= m; i++) { if(cnt[i]) { ans += cnt[i]*n/((LL)i*i); } } ans = n - ans; printf("%lld\n",ans); } return 0; }