版权声明:转载注明出处,谢谢,有问题可以向博主联系 https://blog.csdn.net/VictoryCzt/article/details/85081828
【题目地址】
题意简述
给定
T,K,表示有
T组询问,每组给定
n,m,求下面式子的值:
i=1∑nj=1∑mgcd(i,j)K
输出在
mod109+7意义下的值。
n,m,K≤5×106,T≤2000
其实莫比乌斯反演的题目大多都是套路啦QWQ
根据套路,我们枚举
gcd,即可将原式转换为(这里默认
n≤m,如果不满足则交换):
=d=1∑ndKi=1∑nj=1∑m[gcd(i,j)=d]=d=1∑ndKi=1∑⌊dn⌋j=1∑⌊dm⌋[gcd(i,j)=1]=d=1∑ndKi=1∑⌊dn⌋j=1∑⌊dm⌋w∣i,w∣j∑μ(w)=d=1∑ndKw=1∑⌊dn⌋μ(w)⌊dwn⌋⌊dwm⌋
这些都是莫比乌斯反演的套路啦,接下来,为了每次能够在
O(n
)的时间内快速回答,我们就枚举
dw,令
T=dw则得到:
T=1∑n⌊Tn⌋⌊Tm⌋d∣T∑dKμ(dT)
然后我们线性筛出后面的:
f(n)=d∣n∑dKμ(dT)
即可(这个显然是个积性函数,
f=idk⨂μ两个积性函数的狄利克雷卷积也是积性函数)。
也可以枚举倍数用
O(n(logn×快速幂))的复杂度算,但是在这个题上面就太慢了,5e6可能有点卡。
我们根据欧拉筛三步走来推:
- 考虑
f(p),
p为质数的值的计算:
d∣p∑dkμ(dp)
显然,
d=1,p这两个,所以直接算出为
pk−1
- 考虑
f(pc),
p为质数的值的计算:
d∣pc∑dkμ(dpc)=i=0∑c(pi)kμ(pipc)=i=0∑c(pi)kμ(pc−i)
由于当指数大于1的时候
μ(pi)=0,所以只有
i=c,c−1两个有值,直接代入计算即可,答案为
pkc−pkc−k。
- 考虑
f(x),
x=pcy,其中
p⊥y。
那么根据积性函数,直接转化为
f(x)=f(pc)f(y)即可,其中的
f(y)=f(pcx)。
上面有些小写
k就是大写的
K,懒得改了QWQ
下面就是代码了:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll Mod=1e9+7;
const int M=5e6+10,MAX=5e6;
int n,m,K,T;
ll fpow(ll a,ll b){
ll ans=1;
for(;b;b>>=1,a=(a*a)%Mod)if(b&1)ans=(ans*a)%Mod;
return ans;
}
ll F[M],prime[M],P[M],Invp[M],cnt;
ll c[M],f[M],p[M];bool vis[M];
void init(){
F[1]=1;
for(int i=2;i<=MAX;i++){
if(!vis[i]){
prime[++cnt]=i;P[i]=fpow(i,K);Invp[i]=fpow(P[i],Mod-2);
F[i]=P[i]-1;c[i]=1;f[i]=i;p[i]=i;
if(F[i]<0)F[i]+=Mod;
}
for(int j=1,v;j<=cnt&&i*prime[j]<=MAX;j++){
v=i*prime[j];
vis[v]=1;
if(!(i%prime[j])){
c[v]=c[i]+1;f[v]=f[i];p[v]=p[i]*f[i];
ll vv=fpow(P[f[v]],c[v]);
F[v]=F[v/p[v]]*(((vv-vv*Invp[f[v]]%Mod)%Mod+Mod)%Mod)%Mod;
break;
}
F[v]=F[i]*F[prime[j]]%Mod;
c[v]=1;f[v]=prime[j];p[v]=prime[j];
}
}
for(int i=2;i<=MAX;i++)F[i]=(F[i]+F[i-1])%Mod;
}
ll solve(){
ll ans=0;
if(n>m)swap(n,m);
for(int i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=(ans+((F[j]-F[i-1])%Mod+Mod)%Mod*(n/i)%Mod*(m/i)%Mod)%Mod;
}
return ans;
}
int main(){
scanf("%d%d",&T,&K);
init();
while(T--){
scanf("%d%d",&n,&m);
printf("%lld\n",solve());
}
return 0;
}
拓展
其实如果这个题目只有一次询问,且
n,m≤108,K≤50的话,无法线性筛的时候我们可以用杜教筛。
原式相当于
idk⨂μ,我们令
f=idk⨂μ,g=1,那么
f⨂g=idk⨂μ⨂1
先把后面两个卷起来可以得到
μ⨂1=ϵ,那么
f⨂g=idk
套入杜教筛的公式中可以得到:
F(n)=i=1∑nik−i=2∑nF(⌊in⌋)
其中
ik的前缀和可以用拉格朗日差值法在
O(klogk)的时间内求出,所以总的复杂度为
O(n32klogk),在3s左右能跑出
n≤108,K≤50
End
吐槽:莫比乌斯反演和杜教筛的题目都是好多套路和很多神奇的式子啊QWQ,要多写写题,总结总结
其实很多时候杜教筛不知道用什么
g函数去卷要求的
f函数,可以根据经验积累,或者使用贝尔级数之类的去推。
如果杜教筛中还有不好求的前缀和,可以再套一层杜教筛,复杂度仍然为
O(n32),只是空间时间常数大了。