题意:求[a,b]区间里面,与c互质的数的个数。
范围:0<a,b<=10^15,0<c<10^9。
分析:
先将c分解质因数,根据c的范围可以判断质数的范围不超过x个。(x:自己线性筛素数后,从小到大乘一下,看当乘到多少个的时候,积大于10^9,则可以判断c的最多质因数个数)。
假设c的质因数有2,3,5;
则[a,b]区间里,包含质因数2的数的个数为b/2-(a-1)/2;
同理质因数3,5等,也是这样求。
然后根据容斥原理,包含一个质因数-包含两个质因数+包含三个质因数-包含四个质因数……,一次类推,即可得到结果。
注意边界问题,区间[a,b]中a和b也包含在内。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
long long a,b,n;
vector<long long> vt;
long long solve(long long x,long long n){
vt.clear();
long long i,j;
for(i=2;i*i<=n;i++) //对n进行素数分解
if(n%i==0){
vt.push_back(i);
while(n%i==0)
n/=i;
}
if(n>1)
vt.push_back(n);
long long sum=0,val,cnt;
for(i=1;i<(1<<vt.size());i++){ //用二进制来1,0来表示第几个素因子是否被用到,如m=3,三个因子是2,3,5,则i=3时二进制是011,表示第2、3个因子被用到
val=1;
cnt=0;
for(j=0;j<vt.size();j++)
if(i&(1<<j)){ //判断第几个因子目前被用到
val*=vt[j];
cnt++;
}
if(cnt&1) //容斥原理,奇加偶减
sum+=x/val;
else
sum-=x/val;
}
return x-sum;
}
int main(){
int t,cases=0;
scanf("%d",&t);
while(t--){
cin>>a>>b>>n;
cout<<"Case #"<<++cases<<": "<<solve(b,n)-solve(a-1,n)<<endl;
}
return 0;
}