有关资料:
定义及性质证明
线性筛法
相关题目
入门题:hdu 1695
题目大意:求满足x属于区间[1,m]与y属于区间[1,n],且gcd(x,y)=k的数对(x,y)个数。(x,y)与(y,x)属于算作同一个数对。
分析:问题与求x∈[1,m/k],y∈[1,n/k]且gcd(x,y)=1数对(x,y)个数等价。。
设f(i)表示x∈[1,m/k],y∈[1,n/k]且gcd(x,y)=i的数对个数,相应地设F[i]表示x∈[1,m/k],y∈[1,n/k]且gcd(x,y)能被i整除的数对x,y个数。
显然有F[i]=sigma(f[d]) (其中d|i,即d为i的因子)
而F[i]容易求出:F[i]=[a/i][b/i] (a=m/k,b=n/k, []表示向下取整)
于是根据莫比乌斯反演定理,有f[i]=sigma(u[d/i]]*F[d]) 其中i|d
要求的值为f[1]=sigma(u[d]*F[d])
#include <stdio.h> #define N 100005 typedef long long LL; int min(int a,int b) {return a<b?a:b;} int u[N],p[N],v[N]; void init() { int i,j,t=0; u[1]=1; for(i=2;i<N;++i) { if(!v[i]) p[t++]=i,u[i]=-1; for(j=0;j<t&&p[j]*i<N;++j) { v[p[j]*i]=1; if(i%p[j]==0) {u[p[j]*i]=0;break;} u[i*p[j]]=-u[i]; } } } int main() { int ca,n,i,t,a,b,c,d,k; LL ans,tmp; init(); scanf("%d",&n); for(ca=1;ca<=n;++ca) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(!k) {printf("Case %d: 0\n",ca);continue;} //注意k=0的时候 tmp=ans=0; b/=k,d/=k; t=min(b,d); for(i=1;i<=t;++i) {tmp+=(LL)u[i]*(t/i)*(t/i);ans+=(LL)u[i]*(b/i)*(d/i);} ans-=tmp/2; printf("Case %d: %lld\n",ca,ans); } return 0; }
另外还有bzoj 2301和这题差不多,在资料里面已经分析了。用到了分块加速