HDU 4135 Co-prime(容斥原理)
阿新 • • 發佈:2020-08-27
題目大意
求區間內與n互質的數的數量。
解題思路
對於區間顯然用[b,1]-[1,a-1]的結果就行了。反過來想,從原來的數中刪去與n不互質的數。將n分解質因數,然後利用容斥原理去掉與n有公因數的數即可。
假設分解質因數的結果是2,3,5,觀察發現結果就是去掉能被2,3,5整除的數,加上能被2和3,2和5,3和5整除的數,加上能被2和3和5整除的數,當去掉的數是一個奇數項時是減號,偶數項時時加號。同時,每新加入一個質因子,就是在前面的結果上都乘上這個質因子(假設第一個數是1)。
程式碼
const int maxn = 1e5+10; const int maxm = 2e2+10; int p[maxn], u[maxn], q[maxn] = {-1}, __q, k; vector<int> tmp; ll solve(ll k, ll x) { for (int i = 1; (ll)p[i]*p[i]<=x; ++i) if (x%p[i]==0) { while(x%p[i]==0) x/=p[i]; tmp.push_back(p[i]); } if (x>1) tmp.push_back(x); ll res = k; __q = 1; for (auto num : tmp) { int t = __q; for (int i = 0; i<t; ++i) q[__q++] = -q[i]*num; } for (int i = 1; i<__q; ++i) res -= k/q[i]; tmp.clear(); return res; } int main() { for (int i = 2; i<maxn; ++i) { if (!u[i]) u[i] = p[++p[0]] = i; for (int j = 1; i*p[j]<maxn; ++j) { u[i*p[j]] = p[j]; if (i%p[j]==0) break; } } int t; scanf("%d", &t); while(t--) { ll a, b, c; scanf("%lld%lld%lld", &a, &b, &c); printf("Case #%d: %lld\n", ++k, solve(b, c)-solve(a-1, c)); } return 0; }