BZOJ3994: [SDOI2015]约数个数和
$n \leq 50000,m \leq 50000$,求$\sum_{i=1}^n\sum_{j=1}^md(ij)$。
$d(ij)=\sum_{a|i}\sum_{b|j}[(a,b)=1]$,把$a$选中的质因数的次数加上$j$的质因数次数,就是$a$算“比$j$次数多的质因子”,$b$算“次数不超过$j$的质因子”。
$\sum_{i=1}^n\sum_{j=1}^md(ij)$
$=\sum_{i=1}^n\sum_{j=1}^m\sum_{a|i}\sum_{b|j}[(a,b)=1]$
$=\sum_{a=1}^{n}\sum_{b=1}^{m}\left \lfloor \frac{n}{a} \right \rfloor\left \lfloor \frac{m}{b} \right \rfloor\sum_{t|a\wedge t|b}\mu(t)$
$=\sum_{t=1}^n \mu(t)\sum_{c=1}^{\left \lfloor \frac{n}{t} \right \rfloor}\sum_{d=1}^{\left \lfloor \frac{m}{t} \right \rfloor}\left \lfloor \frac{n}{tc} \right \rfloor\left \lfloor \frac{m}{td} \right \rfloor$
后面那东西预处理一下。
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\n",ans); 54 } 55 return 0; 56 }