Description:
求$ sum_{i=1}^n sum_{j=1}^m lcm(i,j) $
Hint:
$ n,m<=10^7 $
Solution:
这题有每次询问 (O(n)) 做法,然而原题是多组询问,所以还是好好推 (O(sqrt[]{n})) 做法
首先:
(Ans=sum_{d=1}^{n}d * sum_{i=1}^n sum_{j=1}^m i * j * [gcd(i,j)==1] )
$Ans=sum_{d=1}^{n}d * sum_{k=1}^{lfloor frac{n}{d} floor} mu(k) * k^2 sum_{i=1}^{lfloor frac{n}{kd} floor} sum_{j=1}^{lfloor frac{m}{kd} floor } i * j $
换元得:
(Ans=sum_{T=1}^{n} sum_{i=1}^{lfloor frac{n}{T} floor} sum_{j=1}^{lfloor frac{m}{T} floor } i * j * sum_{k|T} mu(k) * k^2 * d )
$Ans=sum_{T=1}^{n} sum_{i=1}^{lfloor frac{n}{T} floor} sum_{j=1}^{lfloor frac{m}{T} floor } i * j * (T * sum_{k|T} mu(k) * k) $
易知 (g(T)=sum_{k|T} mu(k) * k) 为积性函数
前面的$ sum_{i=1}^{lfloor frac{n}{T} floor} sum_{j=1}^{lfloor frac{m}{T} floor }i * j$ 就是两个等差数列相乘
后面的线性筛处理出(T*g(T))的前缀和即可
#include<bits/stdc++.h>
using namespace std;
const int mxn=1e7+5,mod=20101009;
int n,m,tot;
int p[mxn],vis[mxn];
long long g[mxn],f[mxn];
void sieve(int lim)
{
g[1]=1;
for(int i=2;i<=lim;++i) {
if(!vis[i]) g[i]=1-i,p[++tot]=i;
for(int j=1;j<=tot&&p[j]*i<=lim;++j) {
vis[p[j]*i]=1;
if(i%p[j]) g[p[j]*i]=g[i]*g[p[j]]%mod;
else {g[p[j]*i]=g[i];break; }
}
}
for(int i=1;i<=lim;++i)
f[i]=(f[i-1]+g[i]*i%mod)%mod;
}
int main()
{
scanf("%d%d",&n,&m); int ans=0;
sieve(10000000); if(n>m) swap(n,m);
for(int l=1,r;l<=n;l=r+1) {
r=min(n/(n/l),m/(m/l)); int x=n/l,y=m/l;
ans=(ans+1ll*(1ll*x*(x+1)/2%mod)*(1ll*y*(y+1)/2%mod)%mod*((f[r]-f[l-1]+mod)%mod)%mod)%mod;
}
printf("%d
",(ans+mod)%mod);
return 0;
}