vi.于神之怒加强版
在这之前,我们引出一个数论函数\(id^k(x)=x^k\)。这个函数就是整数域上的\(k\)次函数。很明显,它是积性函数,准确地说,是完全积性函数。
它的两个特例,一是\(k=1\),就是我们之前提到的\(id\)函数。二是\(k=0\),即\(id^0\)函数。因为\(\forall x\in\mathbb{N}^+,id^0(x)=1\),因此这个函数有一个形象的名字:“1函数”,即\(1(x)\)。
在上一题中,我们最大的任务是求出\(\sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)\),而这个东西,我们有\(\sqrt{n}\)复杂度的\(\sum\limits_{T=1}^{\min(n,m)}\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor((id*\mu)(T))\)。
在这道题中,\(\gcd(i,j)\)变成了\(\gcd^k(i,j)\)。相应地,如果你把它再证明解一遍的话,就会发现这道题的答案为\(\sum\limits_{T=1}^{\min(n,m)}\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor((id^k*\mu)(T))\)。
显然,后面的东西是积性函数。我们设\(g=id^k*\mu\)。
因为\(g\)是积性函数,所以如果有\(x=\prod\limits_{i=1}^n(P_i)^{a_i}\),那么\(g(x)=\prod\limits_{i=1}^ng((P_i)^{a_i})\)。
代入\(g\)的定义:\(g(T)=\sum_{d|T}id^k(d)\mu({\dfrac{T}{d}})\),得\(g(x)=\prod\limits_{i=1}^n\sum_{d|(P_i)^{a_i}}id^k(d)\mu({\dfrac{(P_i)^{a_i}}{d}})\)。
当\(d<P_i^{a_i-1}\)时,\(\mu({\dfrac{(P_i)^{a_i}}{d}})=0\)。因此我们只用考虑\(d=P_i^{a_i-1}\)和\(P_i^{a_i}\)。
则\(g(x)=\prod\limits_{i=1}^nid^k(P_i^{a_i-1})\mu(P_i)+id^k(P_i^{a_i})\mu(1)\)。
代入\(id^k\)和\(\mu\)的定义,得\(g(x)=\prod\limits_{i=1}^n(P_i^{(a_i-1)*k})*(-1)+(P_i^{a_i*k})*1\)
则有\(g(x)=\prod\limits_{i=1}^n(P_i^{(a_i-1)*k})*(P_i^{a_i}-1)\)。依照这个定义,我们就可以写出线性筛的程序了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int T,n,m,k,g[5001000],f[5001000],pri[5001000],res;
int ksm(int x,int y){
int res=1;
for(;y;x=(1ll*x*x)%mod,y>>=1)if(y&1)res=(1ll*res*x)%mod;
return res;
}
void getg(int N){
g[1]=1;
for(int i=2;i<=N;i++){
if(!pri[i])pri[++pri[0]]=i,f[pri[0]]=ksm(i,k),g[i]=(f[pri[0]]-1+mod)%mod;
for(int j=1;j<=pri[0]&&1ll*i*pri[j]<=N;j++){
pri[i*pri[j]]=true;
if(!(i%pri[j])){
g[i*pri[j]]=1ll*g[i]*f[j]%mod;
break;
}
g[i*pri[j]]=1ll*g[pri[j]]*g[i]%mod;
}
}
for(int i=1;i<=N;i++)g[i]=(g[i-1]+g[i])%mod;
}
int main(){
scanf("%d%d",&T,&k),getg(5000000);
while(T--){
scanf("%d%d",&n,&m),res=0;
for(int l=1,r;l<=min(n,m);l=r+1)r=min(n/(n/l),m/(m/l)),(res+=1ll*(g[r]-g[l-1]+mod)%mod*(n/l)%mod*(m/l)%mod)%=mod;
printf("%d\n",res);
}
return 0;
}