bzoj3157&&3516国王奇遇记(dp)

传送门
传送门
随便推一波式子然后O(m^2)dp即可
f ( i ) = ∑ k = 1 n k i m k f(i)=\sum_{k=1}^nk^im^k f(i)=k=1nkimk
然后用扰乱法化简:
( m − 1 ) f ( i ) = ∑ k = 1 n k i m k + 1 − ∑ k = 1 n k i m k (m-1)f(i)=\sum_{k=1}^nk^im^{k+1}-\sum_{k=1}^nk^im^k (m1)f(i)=k=1nkimk+1k=1nkimk
最后化简出来可以 O ( m 2 ) O(m^2) O(m2)递推
注意特判 m = 1 m=1 m=1的情况。
代码:

#include
#define ri register int
using namespace std;
const int mod=1e9+7;
typedef long long ll;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1005;
int n,m,f[N],inv[N],fac[N],ifac[N],d;
inline void init(){
    inv[1]=ifac[0]=ifac[1]=fac[0]=fac[1]=1;
    for(ri i=2;i<=m;++i)fac[i]=mul(fac[i-1],i);
    for(ri i=2;i<=m;++i)inv[i]=mul(inv[mod-mod/i*i],mod-mod/i),ifac[i]=mul(ifac[i-1],inv[i]);
}
inline int C(int n,int m){return mul(fac[n],mul(ifac[m],ifac[n-m]));}
int main(){
    cin>>n>>m;
    if(m==1)return cout<<(ll)n*(n+1)/2%mod,0;
    init();
    f[0]=mul(dec(d=ksm(m,n+1),m),inv[m-1]);
    for(ri t,w=n,i=1;i<=m;++i,Mul(w,n)){
        f[i]=mul(w,d);
        for(ri j=0,ff=i&1;j<i;++j,ff^=1)t=mul(f[j],C(i,j)),ff?Dec(f[i],t):Add(f[i],t);
        Mul(f[i],inv[m-1]);
    }
    cout<<f[m];
    return 0;
}

你可能感兴趣的:(#,dp,#,数学)