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
容斥定理
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<cmath>
#define LL unsigned long long
using namespace std;
const int N = 2*1e5+10;
const int inf = 0x3f3f3f3f;
const double esp = 1e-6;
using namespace std;
LL prime[N];
LL sprime[N];
bool pp[N];
LL k,cnt;
void get_prime()
{
memset(pp, 1, sizeof(pp));
for(LL i=2; i<N; i++)
{
if(pp[i])
{
prime[k++]=i;
for(LL j=i+i; j<N; j+=i)
pp[j]=0;
}
}
}
void CF_yinzi(LL n)//分解质因子
{
cnt=0;
LL t=(LL)sqrt(1.0*n);
for(LL i=0; prime[i]<=t; i++)
{
if(n%prime[i]==0)
{
sprime[cnt++]=prime[i];
while(n%prime[i]==0)
n/=prime[i];
}
}
if(n>1)
sprime[cnt++]=n;
}
LL sovle(LL n)
{
LL q[N];
LL sum=0;
LL t=1;
q[0]=-1;
for(LL i=0; i<cnt; i++)
{
LL x=t;
for(LL j=0; j<x; j++)
{
q[t]=q[j]*sprime[i]*(-1);
t++;
}
}
for(LL i=1; i<t; i++)
sum+=n/q[i];
return sum;
}
int main()
{
int T;
LL a,b,n;
LL ans;
get_prime();
scanf("%d",&T);
while(T--)
{
cin>>a>>b>>n;
CF_yinzi(n);
ans=( b-sovle(b) ) - ( a - 1 - sovle(a-1) );
cout<<ans<<endl;
}
return 0;
}