题目大意
给定n,m,求:
∑i=1n∑j=1mlcm(i,j)
Solution
令p=gcd(i,j),且min{n,m}=n。
∑i=1n∑j=1mlcm(i,j)
=∑p=1n∑i=1⌊np⌋∑j=1⌊mp⌋ijp⋅ε(gcd(i,j))
=∑p=1n∑i=1⌊np⌋∑j=1⌊mp⌋ijp⋅μ(gcd(i,j))∗1
=∑p=1n∑i=1⌊np⌋∑j=1⌊mp⌋ijp∑(d|i)∧(d|j)μ(d)
=∑p=1np∑d=1⌊np⌋μ(d)d2∑i=1⌊ndp⌋i∑j=1⌊mdp⌋j
令q=dp,S(n)= ∑ni=1i
则原式=
∑q=1nqS(⌊nq⌋)S(⌊mq⌋)∑d|qμ(d)d
令F(q)= ∑d|qμ(d)d
则原式=
∑q=1nqS(⌊nq⌋)S(⌊mq⌋)F(q)
其实F类似积性函数,可以用线性筛可以把它求出来。
代码
#include<cstdio>
#include<algorithm>
#define mo 20101009
using namespace std;
typedef long long ll;
int prime[10000010],flag[10000010];
ll F[10000010],S[10000010];
int main()
{
int n,m,cnt=0;
scanf("%d%d",&n,&m);
flag[1]=1;
int MAX=max(n,m);
int MIN=min(n,m);
F[1]=1;
for (int i=2;i<=MAX;i++)
{
if (!flag[i])
prime[++cnt]=i,F[i]=-i+1;
for (int j=1;j<=cnt;j++)
{
if (prime[j]*i>MAX) break;
flag[i*prime[j]]=1;
if (i%prime[j]==0)
{
F[i*prime[j]]=F[i];
break;
}
F[i*prime[j]]=F[i]*F[prime[j]]%mo;
}
}
for (int i=1;i<=MAX;i++)
{
S[i]=S[i-1]+i;
if (S[i]>=mo) S[i]-=mo;
}
ll ans=0;
for (int q=1;q<=MIN;q++)
{
int n1=n/q,m1=m/q;
ll sum=S[n1]*S[m1]%mo;
sum*=q;
sum%=mo;
sum*=F[q];
sum%=mo;
sum=(sum+mo)%mo;
ans+=sum;
if (ans>=mo) ans-=mo;
}
printf("%lld\n",ans);
return 0;
}