「BZOJ4126 」国王奇遇记

「BZOJ4126 」国王奇遇记

题意:

\[\sum_{i=1}^n i^m\times m^i \]

\((1\le n \le 1e9,1\le m\le 5\times 10^5)\)


这类形如 \(\sum_{i=1}^{n}f(i)\times m^i\) 的题目都可以用一种套路解决(\(f(i)\) 表示一个多项式)

直接上结论:

\(S(n)=\sum_{i=1}^ni^m\times m^i\),则存在一个度为 \(m\) 的多项式 \(G(x)\) 满足 \(S(n)=m^n\times G(n)-G(0)\)

证明直接看我这篇博客:https://www.cnblogs.com/nightsky05/p/16200886.html


易知答案为:

\[S(n+1)-f(0)=m^{n+1}\times G(n+1)-G(0)-f(0) \]

根据那篇博客里的内容易知:

\[G(n+1)=\dfrac{G(n)+n^m}{m} \]

推出这条式子之后能用 \(G(0)\)\(k\times G(0)+b\) 表达出所有的 \(G(n)\)

根据高阶公差的知识我们有(也在那篇博客里):

\[\Delta^{k+1} G(0)=\sum_{i=0}^{k+1}(-1)^{k+1-i}\binom{k+1}{i}G(i)=0 \]

得到一个关于 \(G(0)\) 的方程,解得 \(G(0)\) 后依次求得 \(G(0)\dots G(m)\) 直接插值求得 \(G(n+1)\)。然后就可以得到答案了。

复杂度 \(O(m\log n)\)\(\log\) 是逆元的)。

然后我为了方便是用 \(G(1)\dots G(m+1)\) 插值的。

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 5e5+5;
const int MOD = 1e9+7;
ll n,m,K[MAXN],B[MAXN],g[MAXN],I[MAXN],fac[MAXN],df[MAXN],inv[MAXN];
ll qpw(ll x,ll b)
{
	ll r=1;
	for(;b;b>>=1,x=x*x%MOD) if(b&1) r=r*x%MOD;
	return r;
}
ll C(int n,int m){return fac[n]*inv[m]%MOD*inv[n-m]%MOD;}
ll lag()
{
	if(n+1<=m+1) return g[n+1];
	ll P=1;
	for(int i=1;i<=m+1;++i) P=P*(n+1-i)%MOD;
	for(int i=1;i<=m+1;++i) I[i]=qpw(n+1-i,MOD-2);
	ll res=0;
	for(int i=1;i<=m+1;++i)
		res=(res+g[i]*df[m+1-i]%MOD*inv[i-1]%MOD*P%MOD*I[i]%MOD)%MOD;
	return res;
}
int main()
{
	scanf("%lld %lld",&n,&m);
	if(m==1){printf("%lld\n",1ll*(n+1)*n/2);}
	fac[0]=1;df[0]=1;
	for(int i=1;i<=m+1;++i) fac[i]=fac[i-1]*i%MOD,df[i]=df[i-1]*(MOD-i)%MOD;
	df[m+1]=qpw(df[m+1],MOD-2);
	for(int i=m;i>=0;--i) df[i]=df[i+1]*(MOD-i-1)%MOD;
	inv[m+1]=qpw(fac[m+1],MOD-2);
	for(int i=m;i>=0;--i) inv[i]=inv[i+1]*(i+1)%MOD;
	K[0]=1;B[0]=0;
	for(int i=1;i<=m+1;++i)
	{
		ll f=qpw(i-1,m);
		K[i]=K[i-1]*qpw(m,MOD-2)%MOD;B[i]=(B[i-1]+f)%MOD*qpw(m,MOD-2)%MOD;
	}
	ll k=0,b=0;
	for(int i=0;i<=m+1;++i)
	{
		ll t=((i&1)==((m+1)&1))?1:MOD-1;
		k=(k+t*C(m+1,i)%MOD*K[i]%MOD)%MOD;
		b=(b+t*C(m+1,i)%MOD*B[i]%MOD)%MOD;
	}
	g[0]=(MOD-b)*qpw(k,MOD-2)%MOD;
	for(int i=1;i<=m+1;++i)
		g[i]=(K[i]*g[0]%MOD+B[i])%MOD;
	ll gn=lag(),Ans=(gn*qpw(m,n+1)%MOD-g[0]+MOD)%MOD;
	printf("%lld\n",Ans);
	return 0;
}
posted @ 2022-04-27 22:34  夜空之星  阅读(60)  评论(0编辑  收藏  举报