标签:blog io ar os sp for on 2014 log
题意:
给你a,b,c,d,k问 x∈[a,b] y∈[c,d],gcd(x,y)=k 的个数
然后重复算一种 也就是 x=1,y=2和x=2,y=1是一样的。
思路:
首先将b/k,d/k 就转换成了 x∈[a,b] y∈[c,d],gcd(x,y)=1的个数
然后我们枚举其中一个长度较小的区间
找另一个区间与它互质的数
因为数很多,需要预处理一下每个数的质因子
然后就是容斥定理搞了!
然后要注意0的情况!
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"iostream" using namespace std; #define ll __int64 #define N 100000 int ss[N+2],v[N+2]; int mark[N+5][10],mcnt[N+5],c[12]; int ssb() { int cnt=0; memset(ss,0,sizeof(ss)); for(int i=2;i<=N;i++) { if(ss[i]==0) { for(int j=i+i;j<=N;j+=i) ss[j]=1; v[cnt++]=i; } } return cnt; } ll dfs(int k,int x,int lit,int a,int b) { ll ans=0; if(x==lit) { int tep=1; for(int i=0;i<lit;i++) tep*=c[i]; return b/tep-a/tep; } for(int i=k+1;i<mcnt[a];i++) { c[x]=mark[a][i]; ans+=dfs(i,x+1,lit,a,b); } return ans; } ll solve(int x,int y) { ll ans=0; for(int i=1;i<=mcnt[x];i++) { if(i%2) ans+=dfs(-1,0,i,x,y); else ans-=dfs(-1,0,i,x,y); } return ans; } int main() { int t,cas=1,sscnt; cin>>t; sscnt=ssb(); memset(mcnt,0,sizeof(mcnt)); for(int i=0;i<sscnt;i++) { for(int j=v[i];j<=N;j+=v[i]) { mark[j][mcnt[j]++]=v[i]; } } while(t--) { int a,b,c,d,k; scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0) { printf("Case %d: %d\n",cas++,0); continue; } b/=k; d/=k; if(b>d) swap(b,d); ll ans=(b==0?0:d); for(int i=2;i<=b;i++) { ans+=d-i-solve(i,d); } printf("Case %d: %I64d\n",cas++,ans); } return 0; }
标签:blog io ar os sp for on 2014 log
原文地址:http://blog.csdn.net/wdcjdtc/article/details/40897781