P3327/bzoj3994 [SDOI2015]约数个数和(莫比乌斯反演)
无话可补
#include<iostream> #include<cstdio> #include<cstring> #define re register using namespace std; template<typename T>T max(T &a,T &b){return a>b?a:b;} template<typename T>T min(T &a,T &b){return a<b?a:b;} #define N 50001 int t,n,m,pct,pri[N],mu[N],sum[N]; long long g[N],ans; bool v[N]; int main(){ mu[1]=1; for(re int i=2;i<N;++i){ if(!v[i]) pri[++pct]=i,mu[i]=-1; for(re int j=1;j<=pct;++j){ re int tmp=i*pri[j]; if(tmp>=N) break; v[tmp]=1; if(i%pri[j]) mu[tmp]=-mu[i]; else break; }//线性筛 }re int u; for(u=1;u+4<N;u+=4){ sum[u]=sum[u-1]+mu[u]; sum[u+1]=sum[u]+mu[u+1]; sum[u+2]=sum[u+1]+mu[u+2]; sum[u+3]=sum[u+2]+mu[u+3]; }//循环展开:微小加速 for(;u<N;++u) sum[u]=sum[u-1]+mu[u]; for(re int i=1;i<N;++i){ ans=0; for(re int l=1,r;l<=i;l=r+1){ r=i/(i/l); ans+=1ll*(r-l+1)*(i/l); }g[i]=ans; } scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); if(n>m) swap(n,m); ans=0; for(re int l=1,r;l<=n;l=r+1){ r=min(n/(n/l),m/(m/l)); ans+=1ll*(sum[r]-sum[l-1])*g[n/l]*g[m/l]; }printf("%lld\n",ans); }return 0; }