hdu 1695 http://acm.hdu.edu.cn/showproblem.php?pid=1695
思路:gcd(x,y)==k等价于gcd(x/k,y/k)==1.。。。那么也就是求1~x/k与1~y/k两区间内互斥的对数有多少。那么1-x/k之间的可以通过欧拉函数求得,而x/k-y/k之间的可以通过质因数分解,然后简单容斥就好了。。。。坑点(k==0)。。。dfs容斥不会的我这里有一个比较好理解的博客
//452MS 2360K hdu 1695 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> using namespace std; const int maxn=100010; int prime[maxn]; int nprime; int isprime[maxn]; int phi[maxn]; void get_phi() { for(int i=1;i<maxn;i++) phi[i]=i; for(int i=2;i<maxn;i+=2) phi[i]/=2; for(int i=3;i<maxn;i+=2) { if(phi[i]==i) { for(int j=i;j<maxn;j+=i) phi[j]=phi[j]/i*(i-1); } } } void get_prime() { memset(isprime,0,sizeof(isprime)); nprime=0; prime[nprime++]=2; for(int i=3;i<=1000;i+=2) { if(!isprime[i]) { prime[nprime++]=i; for(int j=i*i;j<=1000;j+=2*i) isprime[j]=1; } } } long long ans; int yinzi[maxn]; int cnt=0; long long sum; int a,b,c,d,k; void dfs(int temp,int num,int tot,int val)//扫描到第temp个因子,参与计算的因子个数为num,总共有tot个因子,当前计算的值为val { if(num==tot) { sum+=b/val; return; } if(temp==cnt) return ; dfs(temp+1,num+1,tot,val*yinzi[temp]); dfs(temp+1,num,tot,val); } long long rongci() { long long s=0; for(int i=1;i<=cnt;i++)//对因子个数枚举,奇数加偶数减 { sum=0; dfs(0,0,i,1); if(i&1) s+=sum; else s-=sum; } return b-s; } int main() { //freopen("in.txt","r",stdin); int T_T; get_prime(); get_phi(); scanf("%d",&T_T); for(int kase=1;kase<=T_T;kase++) { printf("Case %d: ",kase); scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0) { printf("0\n"); continue; } ans=0; b/=k,d/=k; if(b>d) swap(b,d); for(int i=1;i<=b;i++) ans+=phi[i]; for(int i=b+1;i<=d;i++) { a=i; cnt=0; for(int j=0;j<nprime&&prime[j]*prime[j]<=a;j++) { if(a%prime[j]==0) { yinzi[cnt++]=prime[j]; while(a%prime[j]==0) a/=prime[j]; } } if(a>1) yinzi[cnt++]=a; ans+=rongci(); } printf("%I64d\n",ans); } return 0; }