Description
给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。
两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的。
Input
第一行输入一个整数T(1 <= T <= 100),表示T组测试数据。
接下来T行,每行3个整数a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔开。
Output
输出一个整数表示和n互质的数的个数。
Sample Input
2
1 10 2
3 10 5
Sample Output
5
6
注释都加在AC代码里面了,大家可以看下。
下面是AC代码:
#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(){
//freopen("input.txt","r",stdin);
int t,cases=0;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld",&a,&b,&n);
printf("%lld\n",solve(b,n)-solve(a-1,n));
}
return 0;
}