题意:
给出A,B,N,求出[A,B]范围内与N互素的数字的个数。
即B范围内的不与N互素的数减去A范围内不与N互素的数,把[1,A],[1,B]中不与N互素的数分别求出来,再减掉就是和N互素的数了。
那么首先将N分解质因数,因子和因子的倍数可以被除尽,一定不与N互素,把这些数都记下来,筛法求素数即可~
然后把这些数和倍数加起来?果断会有重复,所以这就到容斥原理了,其实这个画个韦恩图就好~
奇数加偶数减,用队列,位运算,dfs都可以实现,不过那个位运算的搞了好久现在暂时还是没懂。。
下面的代码是队列。
#include<stdio.h>
#include<string.h>
using namespace std;
long long a[1000],num;
void prime(long long n)
{
long long i;
num=0;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
a[num++]=i;
while(n%i==0)
n=n/i;
}
}
if(n>1)
a[num++]=n;
}
long long get(long long m)
{
long long que[10000],k,t=0,sum=0;
que[t++]=-1;
for(int i=0;i<num;i++)
{
k=t;
for(int j=0;j<k;j++)
que[t++]=que[j]*a[i]*(-1);
}
for(int i=1;i<t;i++)
sum=sum+m/que[i];
return sum;
}
int main()
{
long long T,x,y,n,cnt;
while(scanf("%lld",&T)!=EOF)
{
for(int i=1;i<=T;i++)
{
scanf("%lld%lld%lld",&x,&y,&n);
prime(n);
cnt=y-get(y)-(x-1-get(x-1));
printf("Case #%d: ",i);
printf("%lld\n",cnt);
}
}
return 0;
}