http://acm.hdu.edu.cn/showproblem.php?pid=4135
给定一个数n,求某个区间[a,b]内有多少数与这个数互质。
对于一个给定的区间,我们如果能够求出这个区间内所有与其不互质的数的个数的话,那么互质数的个数也就求出来。
任何与N不互质的数一定是其某一个质因子的倍数,所以我们通过某一个质因子能够确定一个范围内的有多少个数该质因子的倍数的数。但是这并不是所有不互质数的充分条件,对于另外的质因子同样满足能够确定一系列的数,我们要做的就是容斥定理求他们的并集。num除以奇数个数相乘的时候是加,num除以偶数个数相乘的时候是减。
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <stack> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%I64d%I64d%I64d",&x,&y,&z) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; const int maxn = 1e5+5; LL n,a,b; vector<LL> q; LL ans(LL x) { LL res = 0; for(LL i = 1;i < (1LL<<q.size());++i){ LL u = 1,cnt = 0; for(int j = 0;j < q.size();++j) if(i & (1LL<<j)) cnt++,u *= q[j]; if(cnt & 1) res += x / u; else res -= x / u; } return res; } int main() { int _;RD(_);for(int cas = 1;cas <= _;++cas){ printf("Case #%d: ",cas); RD3(a,b,n); q.clear(); for(LL j = 2;j * j <= n;++j)if(n%j == 0){ q.push_back(j); while(n%j == 0) n/=j; } if(n != 1) q.push_back(n); printf("%I64d\n",b - ans(b) - (a - 1 - ans(a-1))); } return 0; }