版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/86563299
解析:
数学题就不废话了,我们要求的是这个式子:
i=1∑nj=1∑mlcm(i,j)
还是转化成
gcd,一波常规操作:
Ans===i=1∑nj=1∑mgcd(i,j)i×jd=1∑min(n,m)i=1∑nj=1∑mdi×j[gcd(i,j)=d]d=1∑min(n,m)di=1∑⌊dn⌋j=1∑⌊dm⌋ij[gcd(i,j)=1]
好了,有这种东西就可以上
e的反演了,而且上面这个东西:
∑i=1⌊dn⌋∑j=1⌊dm⌋ij可以用分配率拆开,可以
O(1)算出。
为了方便,定义函数
S(n)=∑i=1ni=2n(n+1)
继续推式子:
Ans===d=1∑min(n,m)d⋅S(⌊dn⌋)S(⌊dm⌋)t∣gcd(i,j),i≤⌊dn⌋,j≤⌊dm⌋∑μ(t)d=1∑min(n,m)d⋅t=1∑⌊dmin(n,m)⌋t2μ(t)⋅S(⌊dtn⌋)S(⌊dtm⌋)T=1∑min(n,m)S(⌊Tn⌋)S(⌊Tm⌋)Td∣T∑dμ(d)
前面的已经可以O(1)求了,后面的这个东西看上去不是很好办:
T∑d∣Tdμ(d)
令
F(T)=∑d∣Tdμ(d)
其实
F可以在线性筛的时候一起处理出来。
首先
F(1)=1
对于
p∈P,F(p)=1−p
扫描二维码关注公众号,回复:
5011350 查看本文章
对于
p∈P,a∈N∗,p∤a,F(ap)=F(a)F(p)
对于
p∈P,a∈N∗,p∣a,F(ap)=F(a)
这个通过新增一个质因子会产生的新的因子的贡献就可以看出了。
其实
F就是一个积性函数,这里就不证了。通过构造
F(ab)和
F(a)×F(b)的每一项的一一对应就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const
cs int P=10000007;
cs ll mod=20101009,inv2=mod-mod/2;
bool mark[P];
int prime[P],pcnt,F[P];
inline void linear_sieves(int len=P-7){
F[1]=1;
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i,F[i]=1-i;
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
if(i%prime[j]==0){F[i*prime[j]]=F[i];break;}
F[i*prime[j]]=F[i]*(1-prime[j]);
}
F[i]=((ll)i*F[i]%mod+F[i-1]+mod)%mod;
}
}
inline ll S(cs ll m){
return m*(m+1)%mod*inv2%mod;
}
int n,m;
ll ans;
signed main(){
scanf("%d%d",&n,&m);
if(n>m)swap(n,m);
linear_sieves(n);
for(int re i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=(ans+S(n/i)*S(m/i)%mod*(F[j]-F[i-1]+mod)%mod)%mod;
}
cout<<ans;
return 0;
}