题目求[A,B]区间内与N互质数的个数。
- 可以通过求出区间内与N互质数的个数的前缀和,即[1,X],来得出[A,B]。
- 那么现在问题是求出[1,X]区间内与N互质数的个数,考虑这个问题的逆问题:[1,X]区间内与N不互质数的个数。
- 于是就可以先处理出N的所有质因数{p0,p1,p2,...,pn}。
- 而[1,X]能被pi整除的数有$lfloor frac X{p_i} floor$个,再利用容斥原理除掉质因数公倍数重复计数的部分就能求出不互质个数。
- 最后X减去不互质个数就是互质个数了。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 int prime[33],pn; 5 long long calc(long long n){ 6 long long res=0; 7 for(int i=1; i<(1<<pn); ++i){ 8 int tmp=1,cnt=0; 9 for(int j=0; j<pn; ++j){ 10 if(((i>>j)&1)==0) continue; 11 ++cnt; 12 tmp*=prime[j]; 13 } 14 if(cnt&1) res+=n/tmp; 15 else res-=n/tmp; 16 } 17 return n-res; 18 } 19 int main(){ 20 long long a,b; 21 int t,n; 22 scanf("%d",&t); 23 for(int cse=1; cse<=t; ++cse){ 24 scanf("%lld%lld%d",&a,&b,&n); 25 pn=0; 26 for(int i=2; i*i<=n; ++i){ 27 if(n%i) continue; 28 while(n%i==0) n/=i; 29 prime[pn++]=i; 30 } 31 if(n!=1) prime[pn++]=n; 32 printf("Case #%d: %lld ",cse,calc(b)-calc(a-1)); 33 } 34 return 0; 35 }