背景:
又是一道水题。
题目传送门:
https://www.luogu.org/problem/P4449
题意:
求
∑
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 \sum_{i=1}^{n}\sum_{j=1}^{m}\gcd(i,j)^k i=1∑nj=1∑mgcd(i,j)k
= ∑ d = 1 min ( n , m ) ∑ i = 1 n ∑ j = 1 m d k [ gcd ( i , j ) = d ] =\sum_{d=1}^{\min(n,m)}\sum_{i=1}^{n}\sum_{j=1}^{m}d^k[\gcd(i,j)=d] =d=1∑min(n,m)i=1∑nj=1∑mdk[gcd(i,j)=d]
= ∑ d = 1 min ( n , m ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ d k [ gcd ( i , j ) = 1 ] =\sum_{d=1}^{\min(n,m)}\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{d}\rfloor}d^k[\gcd(i,j)=1] =d=1∑min(n,m)i=1∑⌊dn⌋j=1∑⌊dm⌋dk[gcd(i,j)=1]
= ∑ d = 1 min ( n , m ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ d k ∑ t ∣ gcd ( i , j ) μ ( t ) =\sum_{d=1}^{\min(n,m)}\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{d}\rfloor}d^k\sum_{t|\gcd(i,j)}\mu(t) =d=1∑min(n,m)i=1∑⌊dn⌋j=1∑⌊dm⌋dkt∣gcd(i,j)∑μ(t)
= ∑ d = 1 min ( n , m ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ d k ∑ t = 1 min ( ⌊ n d ⌋ ⌊ m d ⌋ ) μ ( t ) [ t ∣ gcd ( i , j ) ] =\sum_{d=1}^{\min(n,m)}\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{d}\rfloor}d^k\sum_{t=1}^{\min(\lfloor \frac{n}{d}\rfloor\lfloor \frac{m}{d}\rfloor)}\mu(t)[t|\gcd(i,j)] =d=1∑min(n,m)i=1∑⌊dn⌋j=1∑⌊dm⌋dkt=1∑min(⌊dn⌋⌊dm⌋)μ(t)[t∣gcd(i,j)]
= ∑ d = 1 min ( n , m ) ∑ t = 1 min ( ⌊ n d ⌋ ⌊ m d ⌋ ) μ ( t ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ d k [ t ∣ gcd ( i , j ) ] =\sum_{d=1}^{\min(n,m)}\sum_{t=1}^{\min(\lfloor \frac{n}{d}\rfloor\lfloor \frac{m}{d}\rfloor)}\mu(t)\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{d}\rfloor}d^k[t|\gcd(i,j)] =d=1∑min(n,m)t=1∑min(⌊dn⌋⌊dm⌋)μ(t)i=1∑⌊dn⌋j=1∑⌊dm⌋dk[t∣gcd(i,j)]
= ∑ d = 1 min ( n , m ) ∑ t = 1 min ( ⌊ n d ⌋ ⌊ m d ⌋ ) μ ( t ) ∑ i = 1 ⌊ n d t ⌋ ∑ j = 1 ⌊ m d t ⌋ d k =\sum_{d=1}^{\min(n,m)}\sum_{t=1}^{\min(\lfloor \frac{n}{d}\rfloor\lfloor \frac{m}{d}\rfloor)}\mu(t)\sum_{i=1}^{\lfloor \frac{n}{dt}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{dt}\rfloor}d^k =d=1∑min(n,m)t=1∑min(⌊dn⌋⌊dm⌋)μ(t)i=1∑⌊dtn⌋j=1∑⌊dtm⌋dk
设 T = d t T=dt T=dt,则有:
= ∑ T = 1 min ( n , m ) ∑ t ∣ T μ ( t ) ∑ i = 1 ⌊ n T ⌋ ∑ j = 1 ⌊ m T ⌋ ( T t ) k =\sum_{T=1}^{\min(n,m)}\sum_{t|T}\mu(t)\sum_{i=1}^{\lfloor \frac{n}{T}\rfloor}\sum_{j=1}^{\lfloor \frac{m}{T}\rfloor}(\frac{T}{t})^k =T=1∑min(n,m)t∣T∑μ(t)i=1∑⌊Tn⌋j=1∑⌊Tm⌋(tT)k
= ∑ T = 1 min ( n , m ) ∑ t ∣ T μ ( t ) ⌊ n T ⌋ ⌊ m T ⌋ ( T t ) k =\sum_{T=1}^{\min(n,m)}\sum_{t|T}\mu(t)\lfloor \frac{n}{T}\rfloor\lfloor \frac{m}{T}\rfloor (\frac{T}{t})^k =T=1∑min(n,m)t∣T∑μ(t)⌊Tn⌋⌊Tm⌋(tT)k
= ∑ T = 1 min ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ t ∣ T μ ( t ) ( T t ) k =\sum_{T=1}^{\min(n,m)}\lfloor \frac{n}{T}\rfloor\lfloor \frac{m}{T}\rfloor \sum_{t|T}\mu(t)(\frac{T}{t})^k =T=1∑min(n,m)⌊Tn⌋⌊Tm⌋t∣T∑μ(t)(tT)k
类似埃氏筛预处理后面的
∑
\sum
∑里的,直接整除分块即可。
卡常,你可以线性筛
k
k
k的次方,判断
μ
\mu
μ的值来判断是否进入第二重循环,具体看代码。
我不会告诉你正解是线性筛预处理后面的
∑
\sum
∑。
代码:
#pragma GCC optimize("Ofast")
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
#define LL long long
#define R register
#define I inline
using namespace std;
int n,k;
int prime[5000010],mu[5000010],f[5000010],sum_f[5000010],Pow[5000010];
bool bz[5000010];
I int ksm(int x,int k)
{
int tot=1;
for(;k;k>>=1)
{
if(k&1) tot=(LL)tot*x%mod;
x=(LL)x*x%mod;
}
return tot;
}
I void init(int ma)
{
int t=0;
mu[1]=1;
bz[0]=bz[1]=true;
Pow[0]=1,Pow[1]=1;
for(R int i=2;i<=ma;i++)
{
if(!bz[i]) prime[++t]=i,mu[i]=-1,Pow[i]=ksm(i,k);
for(R int j=1;j<=t&&i*prime[j]<=ma;j++)
{
bz[i*prime[j]]=true;
Pow[i*prime[j]]=(LL)Pow[i]*Pow[prime[j]]%mod;
if(!(i%prime[j]))
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
for(R int i=1;i<=ma;i++)
{
if(!mu[i]) continue;
for(R int j=i;j<=ma;j+=i)
f[j]=((LL)f[j]+mu[i]*Pow[j/i]+mod)%mod;
}
for(R int i=1;i<=ma;i++)
sum_f[i]=(sum_f[i-1]+f[i])%mod;
}
I int work(int n,int m)
{
int sum=0;
for(R int l=1,r;l<=min(n,m);l=r+1)
{
r=min(n/(n/l),m/(m/l));
sum=((LL)sum+((LL)n/l)*((LL)m/l)%mod*((sum_f[r]-sum_f[l-1]+mod)%mod)%mod)%mod;
}
return sum;
}
int main()
{
int T;
int n,m;
scanf("%d %d",&T,&k);
init(5000000);
while(T--)
{
scanf("%d %d",&n,&m);
printf("%d\n",work(n,m));
}
}