题目大意: 求 ∑ i = 1 n ∑ j = 1 m gcd ( i , j ) k \sum_{i=1}^n \sum_{j=1}^m \gcd(i,j)^k ∑i=1n∑j=1mgcd(i,j)k
题解
一看就是莫比乌斯反演嘛~
推推柿子即可:
∑
i
=
1
n
∑
j
=
1
m
gcd
(
i
,
j
)
k
=
∑
i
=
1
n
∑
j
=
1
m
∑
d
=
1
min
(
n
,
m
)
d
k
[
gcd
(
i
,
j
)
=
d
]
=
∑
d
=
1
min
(
n
,
m
)
d
k
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
[
gcd
(
i
,
j
)
=
1
]
=
∑
d
=
1
min
(
n
,
m
)
d
k
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
∑
p
∣
gcd
(
i
,
j
)
μ
(
p
)
=
∑
d
=
1
min
(
n
,
m
)
d
k
∑
p
=
1
min
(
n
,
m
)
μ
(
p
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
[
p
∣
gcd
(
i
,
j
)
]
=
∑
d
=
1
min
(
n
,
m
)
d
k
∑
p
=
1
min
(
n
,
m
)
μ
(
p
)
⌊
n
d
p
⌋
⌊
m
d
p
⌋
\sum_{i=1}^n \sum_{j=1}^m \gcd(i,j)^k\\ =\sum_{i=1}^n \sum_{j=1}^m \sum_{d=1}^{\min(n,m)}d^k [\gcd(i,j)=d]\\ =\sum_{d=1}^{\min(n,m)}d^k \sum_{i=1}^{\lfloor \frac n d \rfloor} \sum_{j=1}^{\lfloor \frac m d \rfloor} [\gcd(i,j)=1]\\ =\sum_{d=1}^{\min(n,m)}d^k \sum_{i=1}^{\lfloor \frac n d \rfloor} \sum_{j=1}^{\lfloor \frac m d \rfloor} \sum_{p|\gcd(i,j)}\mu(p)\\ =\sum_{d=1}^{\min(n,m)}d^k \sum_{p=1}^{\min(n,m)}\mu(p) \sum_{i=1}^{\lfloor \frac n d \rfloor} \sum_{j=1}^{\lfloor \frac m d \rfloor} [p|\gcd(i,j)]\\ =\sum_{d=1}^{\min(n,m)}d^k \sum_{p=1}^{\min(n,m)}\mu(p) \lfloor \frac n {dp} \rfloor \lfloor \frac m {dp} \rfloor
i=1∑nj=1∑mgcd(i,j)k=i=1∑nj=1∑md=1∑min(n,m)dk[gcd(i,j)=d]=d=1∑min(n,m)dki=1∑⌊dn⌋j=1∑⌊dm⌋[gcd(i,j)=1]=d=1∑min(n,m)dki=1∑⌊dn⌋j=1∑⌊dm⌋p∣gcd(i,j)∑μ(p)=d=1∑min(n,m)dkp=1∑min(n,m)μ(p)i=1∑⌊dn⌋j=1∑⌊dm⌋[p∣gcd(i,j)]=d=1∑min(n,m)dkp=1∑min(n,m)μ(p)⌊dpn⌋⌊dpm⌋
设
i
=
d
p
i=dp
i=dp ,更换枚举对象,有:
∑
i
=
1
min
(
a
,
b
)
⌊
n
i
⌋
⌊
m
i
⌋
∑
d
∣
i
d
k
×
μ
(
i
d
)
\sum_{i=1}^{\min(a,b)} \lfloor \frac n i \rfloor \lfloor \frac m i \rfloor \sum_{d|i} d^k \times \mu(\frac i d)
i=1∑min(a,b)⌊in⌋⌊im⌋d∣i∑dk×μ(di)
设
t
(
n
)
=
n
k
,
S
(
n
)
=
∑
d
∣
n
t
(
d
)
×
μ
(
n
d
)
t(n)=n^k,S(n)=\sum_{d|n} t(d)\times \mu(\frac n d)
t(n)=nk,S(n)=∑d∣nt(d)×μ(dn),那么有
∑
i
=
1
min
(
a
,
b
)
⌊
n
i
⌋
⌊
m
i
⌋
S
(
i
)
\sum_{i=1}^{\min(a,b)} \lfloor \frac n i \rfloor \lfloor \frac m i \rfloor S(i)
i=1∑min(a,b)⌊in⌋⌊im⌋S(i)
因为 t t t 是个完全积性函数,所以用线性筛可以 O ( n ) O(n) O(n) 求出,求出来之后预处理 S S S 即可。
很悲剧的是,要是不卡常貌似不是很好过QAQ
但是我还是坚持没有卡常。取而代之的是第一行的代码qwq
代码如下:
#pragma GCC optimize("Ofast")
#include <cstdio>
#include <cstring>
#define maxn 5000010
#define ll long long
#define mod 1000000007
int prime[maxn],tt=0,mu[maxn];
ll t[maxn],S[maxn];
bool v[maxn];
int T,k,n,m;
ll ksm(int x,int y)
{
ll re=1,tot=(ll)x;
while(y>0)
{
if(y%2==1)re=re*tot%mod;
tot=tot*tot%mod;
y/=2;
}
return re;
}
void work()
{
mu[1]=t[1]=1;
for(int i=2;i<=maxn-10;i++)
{
if(!v[i])prime[++tt]=i,mu[i]=-1,t[i]=ksm(i,k);
for(int j=1;j<=tt&&i*prime[j]<=maxn-10;j++)
{
v[i*prime[j]]=true;
t[i*prime[j]]=t[i]*t[prime[j]]%mod;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=maxn-10;i++)
if(mu[i]!=0)for(int j=i;j<=maxn-10;j+=i)
S[j]=(S[j]+(ll)mu[i]*t[j/i]+mod)%mod;
for(int i=2;i<=maxn-10;i++)
S[i]=(S[i]+S[i-1])%mod;
}
inline int min(int x,int y){return x<y?x:y;}
int main()
{
scanf("%d %d",&T,&k);
work();
while(T--)
{
scanf("%d %d",&n,&m);
int l=1,r;
ll ans=0;
while(l<=min(n,m))
{
r=min(n/(n/l),m/(m/l));
ans=(ans+(S[r]-S[l-1]+mod)*(ll)(n/l)%mod*(m/l)%mod)%mod;
l=r+1;
}
printf("%lld\n",ans);
}
}