【题目地址】
给定 T , K T,K T,K,表示有 T T T组询问,每组给定 n , m n,m n,m,求下面式子的值:
∑ i = 1 n ∑ j = 1 m g c d ( i , j ) K \sum_{i=1}^n\sum_{j=1}^mgcd(i,j)^K i=1∑nj=1∑mgcd(i,j)K
输出在 m o d    1 0 9 + 7 \mod 10^9+7 mod109+7意义下的值。
n , m , K ≤ 5 × 1 0 6 , T ≤ 2000 n,m,K\leq 5\times 10^6,T\leq 2000 n,m,K≤5×106,T≤2000
其实莫比乌斯反演的题目大多都是套路啦QWQ
根据套路,我们枚举 g c d gcd gcd,即可将原式转换为(这里默认 n ≤ m n\leq m n≤m,如果不满足则交换):
= ∑ d = 1 n d K ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] = ∑ d = 1 n d K ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ g c d ( i , j ) = 1 ] = ∑ d = 1 n d K ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ∑ w ∣ i , w ∣ j μ ( w ) = ∑ d = 1 n d K ∑ w = 1 ⌊ n d ⌋ μ ( w ) ⌊ n d w ⌋ ⌊ m d w ⌋ =\sum_{d=1}^nd^K\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=d]\\ =\sum_{d=1}^nd^K\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[gcd(i,j)=1]\\ =\sum_{d=1}^nd^K\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{w|i,w|j}\mu(w)\\ =\sum_{d=1}^nd^K\sum_{w=1}^{\lfloor\frac{n}{d}\rfloor}\mu(w)\left\lfloor\frac{n}{dw}\right\rfloor\left\lfloor\frac{m}{dw}\right\rfloor =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 ) O(\sqrt{n}) O(n)的时间内快速回答,我们就枚举 d w dw dw,令 T = d w T=dw T=dw则得到:
∑ T = 1 n ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T d K μ ( T d ) \sum_{T=1}^n\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{m}{T}\right\rfloor\sum_{d|T}d^K\mu(\frac{T}{d}) T=1∑n⌊Tn⌋⌊Tm⌋d∣T∑dKμ(dT)
然后我们线性筛出后面的:
f ( n ) = ∑ d ∣ n d K μ ( T d ) f(n)=\sum_{d|n}d^K\mu(\frac{T}{d}) f(n)=d∣n∑dKμ(dT)
即可(这个显然是个积性函数, f = i d k ⨂ μ f=id^k\bigotimes \mu f=idk⨂μ两个积性函数的狄利克雷卷积也是积性函数)。
也可以枚举倍数用 O ( n ( l o g n × 快 速 幂 ) ) O(n(logn\times快速幂)) O(n(logn×快速幂))的复杂度算,但是在这个题上面就太慢了,5e6可能有点卡。
我们根据欧拉筛三步走来推:
∑ d ∣ p d k μ ( p d ) \sum_{d|p}d^k\mu(\frac{p}{d}) d∣p∑dkμ(dp)
显然, d = 1 , p d=1,p d=1,p这两个,所以直接算出为 p k − 1 p^k-1 pk−1
∑ d ∣ p c d k μ ( p c d ) = ∑ i = 0 c ( p i ) k μ ( p c p i ) = ∑ i = 0 c ( p i ) k μ ( p c − i ) \sum_{d|p^c}d^k\mu(\frac{p^c}{d})\\ =\sum_{i=0}^c(p^i)^k\mu(\frac{p^c}{p^i})\\ =\sum_{i=0}^c(p^i)^k\mu(p^{c-i}) d∣pc∑dkμ(dpc)=i=0∑c(pi)kμ(pipc)=i=0∑c(pi)kμ(pc−i)
由于当指数大于1的时候 μ ( p i ) = 0 \mu(p^i)=0 μ(pi)=0,所以只有 i = c , c − 1 i=c,c-1 i=c,c−1两个有值,直接代入计算即可,答案为 p k c − p k c − k p^{kc}-p^{kc-k} pkc−pkc−k。
那么根据积性函数,直接转化为 f ( x ) = f ( p c ) f ( y ) f(x)=f(p^c)f(y) f(x)=f(pc)f(y)即可,其中的 f ( y ) = f ( x p c ) f(y)=f(\frac{x}{p^c}) f(y)=f(pcx)。
上面有些小写 k k k就是大写的 K K K,懒得改了QWQ
下面就是代码了:
#include
#include
#include
#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];
//ll C[M],mu[M];
void init(){
F[1]=1;
// mu[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);//逆元处理p^{-k}
F[i]=P[i]-1;c[i]=1;f[i]=i;p[i]=i;
if(F[i]<0)F[i]+=Mod;
// mu[i]=Mod-1;
}
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];
// mu[v]=(Mod-mu[i]);
}
}//nlogn的线性筛预处理
// for(int i=1;i<=MAX;i++){
// ll v=fpow(i,K);
// for(int j=i;j<=MAX;j+=i){
// C[j]=(C[j]+v*mu[j/i]%Mod)%Mod;
// }
// }//nlog^2n的预处理
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 ≤ 1 0 8 , K ≤ 50 n,m\leq 10^8,K\leq 50 n,m≤108,K≤50的话,无法线性筛的时候我们可以用杜教筛。
原式相当于 i d k ⨂ μ id^k\bigotimes \mu idk⨂μ,我们令 f = i d k ⨂ μ , g = 1 f=id^k\bigotimes \mu,g=\mathbf{1} f=idk⨂μ,g=1,那么 f ⨂ g = i d k ⨂ μ ⨂ 1 f\bigotimes g=id^k\bigotimes \mu\bigotimes \mathbf1 f⨂g=idk⨂μ⨂1
先把后面两个卷起来可以得到 μ ⨂ 1 = ϵ \mu\bigotimes \mathbf1=\epsilon μ⨂1=ϵ,那么 f ⨂ g = i d k f\bigotimes g=id^k f⨂g=idk
套入杜教筛的公式中可以得到:
F ( n ) = ∑ i = 1 n i k − ∑ i = 2 n F ( ⌊ n i ⌋ ) F(n)=\sum_{i=1}^ni^k-\sum_{i=2}^nF(\left\lfloor\frac{n}{i}\right\rfloor) F(n)=i=1∑nik−i=2∑nF(⌊in⌋)
其中 i k i^k ik的前缀和可以用拉格朗日差值法在 O ( k l o g k ) O(klogk) O(klogk)的时间内求出,所以总的复杂度为 O ( n 2 3 k l o g k ) O(n^{\frac{2}{3}}klogk) O(n32klogk),在3s左右能跑出 n ≤ 1 0 8 , K ≤ 50 n\leq10^8,K\leq 50 n≤108,K≤50
吐槽:莫比乌斯反演和杜教筛的题目都是好多套路和很多神奇的式子啊QWQ,要多写写题,总结总结
其实很多时候杜教筛不知道用什么 g g g函数去卷要求的 f f f函数,可以根据经验积累,或者使用贝尔级数之类的去推。
如果杜教筛中还有不好求的前缀和,可以再套一层杜教筛,复杂度仍然为 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32),只是空间时间常数大了。