LOJ #6207 - 米缇(杜教筛+拉格朗日插值)

LOJ 题面传送门

首先将 \(\sigma_k(ij)\) 展开:

\[\sigma_k(ij)=\sum\limits_{x\mid i}\sum\limits_{y\mid j}[x\perp y](\dfrac{iy}{x})^k \]

具体原理就是我们将一组 \(x\mid i,y\mid j,x\perp y\) 的因子对 \((x,y)\) 对应到一个 \(ij\) 的质因子 \(f(x,y)\) 上。考虑每一个质因子 \(p\),由于 \(x\perp y\) 这个限制的存在,\(x,y\)\(p\) 的次数必须至少有一个为 \(0\),如果 \(x\)\(p\) 次数非零那么我们就令 \(f(x,y)\) 质因子 \(p\) 的次数为 \(i\text{ 中质因子 }p\text{ 的次数}-x\text{ 中质因子 }p\text{ 的次数}\),否则我们令 \(f(x,y)\) 中质因子 \(p\) 的次数为 \(i\text{ 中质因子 }p\text{ 的次数}+y\text{ 中质因子 }p\text{ 的次数}\),不难发现这样一组 \(x\mid i,y\mid j,x\perp y\) 的因子对 \((x,y)\) 与一个 \(ij\) 的质因子形成了双射,并且 \(f(x,y)=(\dfrac{iy}{x})\),因此 \(\sigma_k(ij)=\sum\limits_{x\mid i}\sum\limits_{y\mid j}[x\perp y](\dfrac{iy}{x})^k\)

接下来考虑计算答案:

\[\begin{aligned} ans&=\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sigma_k(ij)\\ &=\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sum\limits_{x\mid i}\sum\limits_{y\mid j}[x\perp y](\dfrac{iy}{x})^k\\ &=\sum\limits_{i=1}^n\sum\limits_{j=1}^n\sum\limits_{x\mid i}\sum\limits_{y\mid j}(\dfrac{iy}{x})^k\sum\limits_{d\mid x,d\mid y}\mu(d)\\ &=\sum\limits_{d=1}^n\mu(d)d^k\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{x\mid i}\sum\limits_{y\mid j}(\dfrac{iy}{x})^d\\ &=\sum\limits_{d=1}^n\mu(d)d^k\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{x\mid i}(\dfrac{i}{x})^k\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{y\mid j}y^k\\ &=\sum\limits_{d=1}^n\mu(d)d^k(\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}i^k\lfloor\dfrac{n}{id}\rfloor)^2 \end{aligned} \]

考虑怎么维护这个东西,首先整除分块,那么前面的东西等价于求 \(\mu·\text{id}_k\) 的前缀和。根据提公因式 \((\mu·\text{id}_k)*(I·\text{id}_k)=(\mu*I)·\text{id}_k=\epsilon\)\(I·\text{id}_k\) 的前缀和对于 \(\le 10^7\) 的部分可预处理,\(>10^7\) 的部分可用拉格朗日插值,这样杜教筛一遍可以求出 \(\mu·\text{id}_k\) 的前缀和。后面的 \(\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}i^k\lfloor\dfrac{n}{id}\rfloor\) 可以再套一层整除分块,\(\text{id}_k\) 的前缀和照样小数据预处理大数据插值。不难发现我们只会在 \(n\) 的关键点处插值,而 \(n\)\(>10^7\) 的关键点最多 \(1000\) 个,因此我们最多插值 \(1000\) 次,总复杂度 \(n^{3/4}+1000k\),可以通过。

const int MAXV=2e7;
const int MAXK=7777;
const int MOD=1e9+7;
ll n;int k,fac[MAXK+5],ifac[MAXK+5];
int qpow(int x,int e){
	int ret=1;
	for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
	return ret;
}
void init_fac(int n){
	for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
	for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
int mu[MAXV+5],pr[MAXV/10+5],prcnt=0,idk[MAXV+5],sum[MAXV+5],smu_pw[MAXV+5];
bool vis[MAXV+5];
void sieve(int n){
	idk[1]=mu[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]) mu[i]=-1,pr[++prcnt]=i,idk[i]=qpow(i,k);
		for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
			vis[pr[j]*i]=1;idk[pr[j]*i]=1ll*idk[pr[j]]*idk[i]%MOD;
			if(i%pr[j]==0) break;mu[i*pr[j]]=-mu[i];
		}
	}
	for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+idk[i])%MOD;
	for(int i=1;i<=n;i++) smu_pw[i]=(0ll+smu_pw[i-1]+mu[i]*idk[i]+MOD)%MOD;
}
int pre[MAXK+5],suf[MAXK+5];
unordered_map<ll,int> _sum,_smu_pw;
int calc_sum(ll n){
	if(k==0) return n%MOD;
	if(n<=MAXV) return sum[n];n%=MOD;
	if(_sum.count(n)) return _sum[n];
	pre[0]=suf[k+3]=1;int res=0;
	for(int i=1;i<=k+2;i++) pre[i]=1ll*pre[i-1]*(n-i+MOD)%MOD;
	for(int i=k+2;i;i--) suf[i]=1ll*suf[i+1]*(n-i+MOD)%MOD;
	for(int i=1;i<=k+2;i++){
		int mul=1ll*sum[i]*pre[i-1]%MOD*suf[i+1]%MOD*ifac[i-1]%MOD*ifac[k+2-i]%MOD;
		if((k+2-i)&1) mul=MOD-mul;res=(res+mul)%MOD;
	} return _sum[n]=res;
}
int calc_smu_pw(ll n){
	if(n<=MAXV) return smu_pw[n];
	if(_smu_pw.count(n)) return _smu_pw[n];
	int res=1;
	for(ll l=2,r;l<=n;l=r+1){
		r=n/(n/l);
		res=(res-1ll*(calc_sum(r)-calc_sum(l-1)+MOD)*calc_smu_pw(n/l)%MOD+MOD)%MOD;
	} return _smu_pw[n]=res;
}
int main(){
	scanf("%lld%d",&n,&k);sieve(MAXV);init_fac(MAXK);
	int res=0;
	for(ll l=1,r;l<=n;l=r+1){
		r=n/(n/l);int sm=0;ll lim=n/l;
		for(ll L=1,R;L<=lim;L=R+1){
			R=lim/(lim/L);
			sm=(sm+1ll*(lim/L)%MOD*(calc_sum(R)-calc_sum(L-1)+MOD))%MOD;
		} sm=1ll*sm*sm%MOD;
		res=(res+1ll*(calc_smu_pw(r)-calc_smu_pw(l-1)+MOD)*sm)%MOD;
	} printf("%d\n",res);
	return 0;
}
posted @ 2021-09-23 23:14  tzc_wk  阅读(88)  评论(1)    收藏  举报