解法:莫比乌斯反演,话说SD去年好像也出了题反演题
贴大神的blog题解
http://blog.codebursts.com/bzoj3994/
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; ll num[50011],mu[50011],ans; int pri[50011],np[50011]; bool p[50011]; int dt,tj,i,j,n,m; void prepare() { ll tz; int i,j,lim,tot; lim=50000; tot=0; memset(p,true,sizeof(p)); num[1]=1; mu[1]=1; for(i=2;i<=lim;i++){ if(p[i]){ pri[++tot]=i; num[i]=2; np[i]=1; mu[i]=-1; } for(j=1;j<=tot;j++){ tz=(ll)pri[j]*i; if(tz>lim)break; p[pri[j]*i]=false; if(i%pri[j]==0){ np[pri[j]*i]=np[i]+1; num[pri[j]*i]=num[i]/(np[i]+1)*(np[i]+2); mu[pri[j]*i]=0; break; } np[pri[j]*i]=1; num[pri[j]*i]=num[i]*2; mu[pri[j]*i]=-mu[i]; } } for(i=1;i<=lim;i++){ num[i]+=num[i-1]; mu[i]+=mu[i-1]; } } int main() { scanf("%d",&dt); prepare(); for(tj=1;tj<=dt;tj++){ scanf("%d%d",&n,&m); if(n>m)swap(n,m); ans=0; for(i=1,j;i<=n;i=j+1){ j=min(n/(n/i),m/(m/i)); ans+=1ll*num[n/i]*num[m/i]*(mu[j]-mu[i-1]); } printf("%lld ",ans); } }