BZOJ2005
首先我们将$2k+1$变换一下.显然有$2k+1=(2gcd{x,y})-1$这个事实.那么我们对$\gcd{x,y}$分区统计,方法参照http://www.contesthunter.org/record/43602我的SXBK题.
#include <cstdio> int m,n,i,j,k; long long fc[200000],ans; int main(){ scanf("%d%d",&n,&m); if(n>m){ n^=m; m^=n; n^=m; } for(i=n;i;--i){ fc[i]=((long long)(n/i))*(m/i); for(j=2*i;j<=m;++j) fc[i]-=fc[j]; ans+=fc[i]*(2*i-1); } printf("%lld\n",ans); return 0; }
求给定$N$,$(x,y,z)=1,1\le x,y,z\le N$中$(x,y,z)$的对数.
我们考虑莫比乌斯反演.
http://quartergeek.com/eight-gcd-problems/ 讲得比较清楚.
#include <cstdio> int pr[100000],pl,mu[2000000],i; int prm[2000000],T,n; int genMu(int n){ int i,j,k; mu[1]=1; for(i=2;i<=n;++i){ if(!prm[i]){ mu[i]=-1; prm[i]=pr[pl++]=i; } for(j=0;j<pl&&(k=pr[j]*i)<=n;++j){ prm[k]=pr[j]; if(prm[i]==pr[j]){ mu[k]=0; break; }else{ mu[k]=-mu[i]; } } } } long long ans; inline long long cb(long long a){ return a*a*a; } inline long long sq(long long a){ return a*a; } int main(){ genMu(1000000); scanf("%d",&T); while(T--){ scanf("%d",&n); ans=3LL; for(i=1;i<=n;++i) ans+=((long long)(mu[i]))*cb((long long)(n/i)); for(i=1;i<=n;++i) ans+=((long long)(mu[i]))*sq((long long)(n/i))*3LL; printf("%lld\n",ans); } return 0; }
BZOJ 1101 (POI)