题意:给你三个数a b n,求a~b 之间与n互质的数的个数 1<=a<=b<=10^15; n<10^9
解析: 暴力枚举出n的质因子,在容斥
#include<iostream>
#include<vector>
#include<math.h>
#include<cstdio>
#include<string.h>
using namespace std;
typedef __int64 LL;
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
vector<int> prime;
LL n,m,a,b,cent,sum,w;
void dfs(int s,LL lcm,int bit)
{
int i;
LL lcm1;
if(bit&1)
{
if(b>=lcm)
sum-=b/lcm;
if(a-1>=lcm)
sum+=(a-1)/lcm;
}
else
{
if(b>=lcm)
sum+=b/lcm;
if(a-1>=lcm)
sum-=(a-1)/lcm;
}
for(i=s+1;i<m;i++)
{
lcm1=lcm*prime[i]; //开始居然直接将lcm的值变了,wa 了好久
if(b>=lcm1)
dfs(i,lcm1,bit+1);
}
}
int main()
{
int i,j,T,t,bit;
LL lcm;
scanf("%d",&T);
for(t=1; t<=T; t++)
{
prime.clear();
scanf("%I64d%I64d%I64d",&a,&b,&n);
for(i=2; i<=sqrt(double(n))+1; i++)
{
if(n%i==0)
prime.push_back(i);
while(n%i==0)
n=n/i;
}
if(n!=1) prime.push_back(n);
m=prime.size();
sum=b-a+1;
for(i=0; i<m; i++)
{
dfs(i,prime[i],1); //dfs回溯容斥
}
/* //二进制的容斥,应该较慢点
for(i=1; i<(1<<m); i++)
{
lcm=1;
bit=0;
for(j=0; j<m; j++)
{
cent=1<<j;
if(cent&i)
{
bit++;
lcm=lcm*prime[j]/gcd(lcm,prime[j]);
}
}
if(bit&1)
{
if(b>=lcm)
sum-=b/lcm;
if(a-1>=lcm)
sum+=(a-1)/lcm;
}
else
{
if(b>=lcm)
sum+=b/lcm;
if(a-1>=lcm)
sum-=(a-1)/lcm;
}
}
*/
printf("Case #%d: %I64d\n",t,sum);
}
return 0;
}