[SDOI2015]约数个数和
https://blog.csdn.net/ab_ever/article/details/76737617
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=50000+5; int n,m,t; ll g[N]; int u[N],su[N]; bool vis[N]; int pri[N],tot; void sieve(){ u[1]=1; for(int i=2;i<=N-3;i++){ if(!vis[i]){ pri[++tot]=i; u[i]=-1; } for(int j=1;j<=tot;j++){ if(pri[j]*i>N-3) break; vis[pri[j]*i]=1; if(i%pri[j]==0){ u[pri[j]*i]=0; break; } else u[pri[j]*i]=-u[i]; } } } ll p[N];//wrk for g void pre(){ for(int i=1;i<=N-3;i++)su[i]=su[i-1]+u[i]; for(int i=1;i<=N-3;i++){ for(int j=i;j<=N-3;j+=i){ p[j]++; } } for(int i=1;i<=N-3;i++) g[i]=g[i-1]+p[i]; } int main(){ sieve(); pre(); cin>>t; while(t--){ scanf("%d%d",&n,&m); int ptr=1; ll ans=0; for(;ptr*ptr<=max(n,m)&&ptr<=min(n,m);ptr++){ ans+=u[ptr]*g[n/ptr]*g[m/ptr]; } if(ptr>min(n,m)) { printf("%lld\n",ans); continue; } if(n>m) swap(n,m); int rn=n/ptr,rm=m/ptr; int pn,pm; while(1){ pn=n/rn,pm=m/rm; int tmp=min(pn,pm); ans+=(su[tmp]-su[ptr-1])*g[rn]*g[rm]; if(tmp==n) break; ptr=tmp+1; rn=n/ptr,rm=m/ptr; } printf("%lld\n",ans); } return 0; } /* Author: *Miracle* Date: 2018/10/4 22:08:25 */