BZOJ3516 国王奇遇记加强版

题目

\[\sum_{i=1}^ni^mm^i\]

\(n\leq 10^9,m\leq 10^3\)

看起来是个暴力好题,考虑倍增暴力搞,即从\(\sum_{i=1}^ni^mm^i\)推到\(\sum_{i=1}^{2n}i^mm^i\)

\[\sum_{i=1}^{2n}i^mm^i=\sum_{i=1}^ni^mm^i+m^n\sum_{i=1}^n(i+n)^{m}m^{i}\]

这个\(\sum_{i=1}^n(i+n)^{m}m^{i}\)二项式定理一下,就是\(\sum_{i=1}^nm^i\sum_{k=0}^m\binom{m}{k}i^kn^{m-k}\)

交换一下\(\sum\),并拆开组合数,就是

\[m!\sum_{k=0}^m\frac{n^{m-k}}{(m-k)!}\times \frac{\sum_{i=1}^ni^km^i}{k!}\]

显然是一个卷积的形式,暴力做就是\(O(m^2\log n)\)的,可以优化到\(O(m\log m\log n)\)但不是NTT模数就算了吧

还有这题怎么1s时限啊,好像只有在DB上能勉强跑过去

代码

#include<bits/stdc++.h>
#define re register
const int mod=1e9+7;
inline int dqm(int x) {return x<0?x+mod:x;}
inline int qm(int x) {return x>=mod?x-mod:x;}
inline int ksm(int a,int b) {
    int S=1;for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)S=1ll*S*a%mod;return S;
}
int n,m,fac[1005],ifac[1005],ans[1005],g[1005],h[1005];
void solve(int n,int *f) {
    if(n==1) {for(re int i=0;i<=m;i++) f[i]=m;return;}
    solve(n>>1,f);int k=n;k>>=1;
    for(re int i=0;i<=m;i++) g[i]=f[i];
    for(re int i=0;i<=m;i++) g[i]=1ll*g[i]*ifac[i]%mod;
    for(re int nw=1,i=0;i<=m;i++,nw=1ll*nw*k%mod) h[i]=1ll*ifac[i]*nw%mod;
    for(re int t=0,i=m;i>=0;g[i]=t,--i,t=0) 
        for(re int j=0;j<=i;j++) t=qm(t+1ll*g[i-j]*h[j]%mod);
    for(re int i=0;i<=m;i++) g[i]=1ll*g[i]*fac[i]%mod;
    for(re int t=ksm(m,k),i=0;i<=m;i++) f[i]=qm(f[i]+1ll*g[i]*t%mod);
    if(!(n&1)) return;int t=ksm(m,n);
    for(re int nw=1,i=0;i<=m;i++,nw=1ll*nw*n%mod) f[i]=qm(f[i]+1ll*t*nw%mod);
}
int main() {
    scanf("%d%d",&n,&m);ifac[0]=fac[0]=1;
    for(re int i=1;i<=m;i++) fac[i]=1ll*fac[i-1]*i%mod;
    ifac[m]=ksm(fac[m],mod-2);
    for(re int i=m-1;i;--i) ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
    solve(n,ans);printf("%d\n",ans[m]);return 0;
}

猜你喜欢

转载自www.cnblogs.com/asuldb/p/12116329.html