题解:
有一个式子:
证明先不说了。
然后倒一波反演:
然后整除分块就好了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 50050 #define ll long long int t,n,m; int pri[N],cnt,mu[N]; ll sum[N],f[N]; bool vis[N]; void get_mu() { mu[1]=sum[1]=1; for(int i=2;i<=50000;i++) { if(!vis[i]) { pri[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt&&i*pri[j]<=50000;j++) { vis[i*pri[j]]=1; if(i%pri[j])mu[i*pri[j]]=-mu[i]; else break; } sum[i]=sum[i-1]+mu[i]; } } void get_f() { for(int x=1;x<=50000;x++) for(int i=1,nxt;i<=x;i=nxt+1) { nxt=x/(x/i); f[x]+=1ll*(nxt-i+1)*(x/i); } } int main() { scanf("%d",&t); get_mu(); get_f(); while(t--) { scanf("%d%d",&n,&m); if(n>m)swap(n,m); ll ans = 0; for(int i=1,nxt;i<=n;i=nxt+1) { nxt = min(n/(n/i),m/(m/i)); ans+=1ll*(sum[nxt]-sum[i-1])*f[n/i]*f[m/i]; } printf("%lld ",ans); } return 0; }