Time Limit: 10 Sec
Memory Limit: 256 MB
Description
给定正整数n,m。求
Input
一行两个整数n,m
Output
一个整数,为答案模1000000007后的值
HINT
1<=n,m<=500000,共有3组数据
题目分析
和 洛谷P1829 [国家集训队]Crash的数字表格的推导过程很像
∑i=1n∑j=1mlcm(i,j)gcd(i,j)=∑i=1n∑j=1m(ijgcd(i,j))gcd(i,j)\sum_{i=1}^n\sum_{j=1}^mlcm(i,j)^{gcd(i,j)}=\sum_{i=1}^n\sum_{j=1}^m(\frac{ij}{gcd(i,j)})^{gcd(i,j)}i=1∑nj=1∑mlcm(i,j)gcd(i,j)=i=1∑nj=1∑m(gcd(i,j)ij)gcd(i,j)
把gcd提出来枚举
∑d=1min(n,m)∑i=1n∑j=1m(ijd)d[gcd(i,j)=d]\sum_{d=1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m(\frac{ij}{d})^{d}[gcd(i,j)=d]d=1∑min(n,m)i=1∑nj=1∑m(dij)d[gcd(i,j)=d]
若gcd(i,j)==dgcd(i,j)==dgcd(i,j)==d,则有gcd(i/d,j/d)=1gcd(i/d,j/d)=1gcd(i/d,j/d)=1
∑d=1min(n,m)∑x=1⌊nd⌋∑y=1⌊md⌋(xd∗ydd)d[gcd(x,y)=1]=∑d=1min(n,m)dd∑x=1⌊nd⌋∑y=1⌊md⌋(xy)d[gcd(x,y)=1]\sum_{d=1}^{min(n,m)}\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{d}\rfloor}(\frac{xd*yd}{d})^{d}[gcd(x,y)=1]=\sum_{d=1}^{min(n,m)}d^d\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{d}\rfloor}(xy)^{d}[gcd(x,y)=1]d=1∑min(n,m)x=1∑⌊dn⌋y=1∑⌊dm⌋(dxd∗yd)d[gcd(x,y)=1]=d=1∑min(n,m)ddx=1∑⌊dn⌋y=1∑⌊dm⌋(xy)d[gcd(x,y)=1]
莫比乌斯反演一下
∑d=1min(n,m)dd∑x=1⌊nd⌋∑y=1⌊md⌋(xy)d∑z∣gcd(x,y)μ(z)=∑d=1min(n,m)dd∑x=1⌊nd⌋∑y=1⌊md⌋(xy)d∑z=1gcd(x,y)μ(z)[z∣gcd(x,y)]\sum_{d=1}^{min(n,m)}d^d\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{d}\rfloor}(xy)^{d}\sum_{z|gcd(x,y)}\mu(z)=\sum_{d=1}^{min(n,m)}d^d\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{d}\rfloor}(xy)^{d}\sum_{z=1}^{gcd(x,y)}\mu(z)[z|gcd(x,y)]d=1∑min(n,m)ddx=1∑⌊dn⌋y=1∑⌊dm⌋(xy)dz∣gcd(x,y)∑μ(z)=d=1∑min(n,m)ddx=1∑⌊dn⌋y=1∑⌊dm⌋(xy)dz=1∑gcd(x,y)μ(z)[z∣gcd(x,y)]
变换一下枚举顺序
∑d=1min(n,m)dd∑z=1min(⌊nd⌋,⌊md⌋)μ(z)∑x=1⌊nd⌋∑y=1⌊md⌋(xy)d[z∣gcd(x,y)]\sum_{d=1}^{min(n,m)}d^d\sum_{z=1}^{min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)}\mu(z)\sum_{x=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{m}{d}\rfloor}(xy)^{d}[z|gcd(x,y)]d=1∑min(n,m)ddz=1∑min(⌊dn⌋,⌊dm⌋)μ(z)x=1∑⌊dn⌋y=1∑⌊dm⌋(xy)d[z∣gcd(x,y)]
x,yx,yx,y的枚举替换成枚举zzz的倍数
∑d=1min(n,m)dd∑z=1min(⌊nd⌋,⌊md⌋)μ(z)∑t1=1⌊ndz⌋∑t2=1⌊mdz⌋(z2t1t2)d=∑d=1min(n,m)dd∑z=1min(⌊nd⌋,⌊md⌋)z2dμ(z)∑t1=1⌊ndz⌋t1d∑t2=1⌊mdz⌋t2d\sum_{d=1}^{min(n,m)}d^d\sum_{z=1}^{min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)}\mu(z)\sum_{t_1=1}^{\lfloor\frac{n}{dz}\rfloor}\sum_{t_2=1}^{\lfloor\frac{m}{dz}\rfloor}(z^2t_1t_2)^{d}=\sum_{d=1}^{min(n,m)}d^d\sum_{z=1}^{min(\lfloor\frac{n}{d}\rfloor,\lfloor\frac{m}{d}\rfloor)}z^{2d}\mu(z)\sum_{t_1=1}^{\lfloor\frac{n}{dz}\rfloor}t_1^d\sum_{t_2=1}^{\lfloor\frac{m}{dz}\rfloor}t_2^{d}d=1∑min(n,m)ddz=1∑min(⌊dn⌋,⌊dm⌋)μ(z)t1=1∑⌊dzn⌋t2=1∑⌊dzm⌋(z2t1t2)d=d=1∑min(n,m)ddz=1∑min(⌊dn⌋,⌊dm⌋)z2dμ(z)t1=1∑⌊dzn⌋t1dt2=1∑⌊dzm⌋t2d
虽然由于每一项几乎都有d次幂不方便维护前缀和
但认真观察发现最后那两个和式每次从上一次d-1次幂继承,只用O(m/d)O(m/d)O(m/d)处理
z2dμ(z)z^{2d}\mu(z)z2dμ(z)需要O(n/d∗logd)O(n/d*logd)O(n/d∗logd)处理
总复杂度是O(nlogn)O(nlogn)O(nlogn)级的
由于每个测试点只有一组数据,完全可以接受
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long lt;
#define lowbit(x) ((x)&(-x))
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int mod=1000000007;
const int maxn=500010;
int T;
int miu[maxn];
int prim[maxn],vis[maxn],cnt;
lt sum[maxn],a[maxn];
lt qpow(lt a,int k)
{
lt res=1;
while(k>0){
if(k&1) res=(res*a)%mod;
a=(a*a)%mod; k>>=1;
}
return res;
}
void Miu(int n)
{
miu[1]=1;
for(int i=2;i<=n;++i)
{
if(!vis[i]) prim[++cnt]=i,miu[i]=-1;
for(int j=1;j<=cnt;++j)
{
if(i*prim[j]>n) break;
vis[i*prim[j]]=1;
if(i%prim[j]==0) break;
else miu[i*prim[j]]=-miu[i];
}
}
}
lt query(int n,int m)
{
lt res=0; if(n>m) swap(n,m);
for(int i=1;i<=m;++i) a[i]=1;
for(int d=1;d<=n;++d)
{
for(lt i=1;i<=m/d;++i)
{
a[i]=a[i]*i%mod;
sum[i]=(sum[i-1]+a[i])%mod;
}
lt tt=0;
for(int j=1;j<=n/d;++j)
{
tt+=(qpow(j,2*d)*miu[j]%mod+mod)%mod * sum[n/(j*d)]%mod * sum[m/(j*d)]%mod;
tt%=mod;
}
res+=qpow(d,d)*tt%mod;
res%=mod;
}
return res;
}
int main()
{
int n=read(),m=read();
Miu(min(n,m));
printf("%lld",query(n,m));
return 0;
}