BZOJ_2820_YY的GCD_莫比乌斯反演
题意&分析:
首先f[i]非积性,但可以通过μ处理,所以我们考虑线筛
f[i*p]=μ[i*p/p‘];
1.当i为质数时f[i]=1;
2.当i%prime[j]==0时i*prime[j]中有两个相同因子的质数乘积,即p=p‘,则f[i*prime[j]]=μ[i];
3.当i%prime[j]!=0时,p!=p‘的情况对f的值有影响.当p‘!=p时μ[i*p/p‘]=-f[i],f[i*prime[j]]=μ[i]-f[i];
再记录下f[i]的前缀和,分块计算
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 #define LL long long 6 int prime[4000010],vis[10000100],miu[10000100],f[10000100],sum[10000100],cnt; 7 int T,n,m; 8 inline void init() 9 { 10 miu[1]=1; 11 for(int i=2;i<=10000000;i++) 12 { 13 if(!vis[i]) 14 { 15 miu[i]=-1; 16 f[i]=1; 17 prime[++cnt]=i; 18 } 19 for(int j=1;j<=cnt&&i*prime[j]<=10000000;j++) 20 { 21 vis[i*prime[j]]=1; 22 if(i%prime[j]==0) 23 { 24 miu[i*prime[j]]=0; 25 f[i*prime[j]]=miu[i]; 26 break; 27 } 28 miu[i*prime[j]]=-miu[i]; 29 f[i*prime[j]]=miu[i]-f[i]; 30 } 31 sum[i]=sum[i-1]+f[i]; 32 } 33 } 34 int main() 35 { 36 init(); 37 scanf("%d",&T); 38 while(T--) 39 { 40 scanf("%d%d",&n,&m); 41 if(n>m)swap(n,m); 42 int lst; 43 LL ans=0; 44 for(int i=1;i<=n;i=lst+1) 45 { 46 lst=min(n/(n/i),m/(m/i)); 47 ans+=1ll*(sum[lst]-sum[i-1])*(n/i)*(m/i); 48 } 49 printf("%lld\n",ans); 50 } 51 } 52