「luogu3172」[SDOI2015]约数个数和
套莫比乌斯反演
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define R register 4 using namespace std; 5 const int N=50010,M=110,maxf=100; 6 int n,m,lim=50000,p[N],tot,cnt[N],f[N],u[N]; 7 bool isp[N]; 8 void pre(){ 9 f[1]=u[1]=1; 10 for(R int i=2;i<=lim;i++){ 11 if(!isp[i]) p[++tot]=i,f[i]=2,cnt[i]=1,u[i]=-1; 12 for(int j=1;j<=tot&&1LL*i*p[j]<=lim;j++){ 13 isp[i*p[j]]=1; 14 if(i%p[j]) f[i*p[j]]=f[i]*2,cnt[i*p[j]]=1,u[i*p[j]]=-u[i]; 15 else{f[i*p[j]]=f[i]/(cnt[i]+1)*(cnt[i]+2),cnt[i*p[j]]=cnt[i]+1,u[i*p[j]]=0;break;} 16 } 17 } 18 for(R int i=2;i<=lim;i++) u[i]=u[i]+u[i-1],f[i]+=f[i-1]; 19 return; 20 } 21 void solve(){ 22 scanf("%d%d",&n,&m); 23 if(n>m) swap(n,m); 24 R int l=1,r; 25 ll res=0; 26 while(l<=n){ 27 r=min(n/(n/l),m/(m/l)); 28 res+=1LL*f[n/l]*f[m/l]*(u[r]-u[l-1]); 29 l=r+1; 30 } 31 printf("%lld\n",res); 32 return; 33 } 34 int main(){ 35 pre(); 36 int t=0; 37 int T; 38 scanf("%d",&T); 39 while(T--) solve(); 40 return 0; 41 }