$n leq 50000,m leq 50000$,求$sum_{i=1}^nsum_{j=1}^md(ij)$。
$d(ij)=sum_{a|i}sum_{b|j}[(a,b)=1]$,把$a$选中的质因数的次数加上$j$的质因数次数,就是$a$算“比$j$次数多的质因子”,$b$算“次数不超过$j$的质因子”。
$sum_{i=1}^nsum_{j=1}^md(ij)$
$=sum_{i=1}^nsum_{j=1}^msum_{a|i}sum_{b|j}[(a,b)=1]$
$=sum_{a=1}^{n}sum_{b=1}^{m}left lfloor frac{n}{a} ight floorleft lfloor frac{m}{b} ight floorsum_{t|awedge t|b}mu(t)$
$=sum_{t=1}^n mu(t)sum_{c=1}^{left lfloor frac{n}{t} ight floor}sum_{d=1}^{left lfloor frac{m}{t} ight floor}left lfloor frac{n}{tc} ight floorleft lfloor frac{m}{td} ight floor$
后面那东西预处理一下。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 //#include<math.h> 5 //#include<queue> 6 #include<algorithm> 7 //#include<iostream> 8 //#include<assert.h> 9 using namespace std; 10 11 int T,n,m; 12 #define maxn 50011 13 #define LL long long 14 LL f[maxn],g[maxn],sumf[maxn]; 15 int miu[maxn],summiu[maxn],prime[maxn],lp; bool notprime[maxn]; 16 void pre(int n) 17 { 18 miu[1]=summiu[1]=1; 19 for (int i=2;i<=n;i++) 20 { 21 if (!notprime[i]) prime[++lp]=i,miu[i]=-1; 22 summiu[i]=summiu[i-1]+miu[i]; 23 for (int tmp,j=1;j<=lp && 1ll*i*prime[j]<=n;j++) 24 { 25 notprime[tmp=i*prime[j]]=1; 26 if (i%prime[j]) miu[tmp]=-miu[i]; 27 else {miu[tmp]=0; break;} 28 } 29 } 30 31 for (int i=1;i<=n;i++) 32 for (int j=1,now,last;j<=i;j=last+1) 33 { 34 now=i/j,last=i/now; 35 f[i]+=(last-j+1)*1ll*now; 36 } 37 } 38 39 int main() 40 { 41 scanf("%d",&T); 42 pre(50000); 43 while (T--) 44 { 45 scanf("%d%d",&n,&m); 46 (n>m) && (n^=m^=n^=m); 47 LL ans=0; 48 for (int i=1,last;i<=n;i=last+1) 49 { 50 last=min(n/(n/i),m/(m/i)); 51 ans+=(summiu[last]-summiu[i-1])*f[n/i]*f[m/i]; 52 } 53 printf("%lld ",ans); 54 } 55 return 0; 56 }