bzoj 3157 国王奇遇记 - 数学

……没有任何算法的推式子……

F k = i = 1 n i k × m i

F k = i = 1 n ( i 1 + 1 ) k × m i 1 + 1

F k = m + i = 1 n 1 ( i + 1 ) k × m i + 1

F k = m ( n + 1 ) k × m n + 1 + i = 1 n ( i + 1 ) k × m i + 1

F k = m ( n + 1 ) k × m n + 1 + i = 1 n j = 0 k ( k j ) i j × m i + 1

F k = m ( n + 1 ) k × m n + 1 + m j = 0 k ( k j ) i = 1 n i j × m i

F k = m ( n + 1 ) k × m n + 1 + m j = 0 k ( k j ) F j

( m 1 ) F k = ( n + 1 ) k × m n + 1 m m j = 0 k 1 ( k j ) F j

F k = ( n + 1 ) k × m n + 1 m m j = 0 k 1 ( k j ) F j m 1

特判m=1的情况,其余这样转移即可,平方复杂度。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 210
#define lint long long
#define mod 1000000007
#define inv(x) fast_pow(x,mod-2)
using namespace std;
int s[N],c[N][N],mi[N];
inline int fast_pow(int x,int k,int ans=1)
{
    for(;k;k>>=1,x=(lint)x*x%mod)
        if(k&1) ans=(lint)ans*x%mod;
    return ans;
}
int main()
{
    int n,m,t;scanf("%d%d",&n,&m),mi[0]=fast_pow(m,n+1),t=inv(m-1);
    if(m==1) return !printf("%lld\n",(lint)n*(n+1)%mod*inv(2)%mod);
    for(int i=1;i<=m;i++) mi[i]=(lint)mi[i-1]*(n+1)%mod;
    s[0]=(lint)t*(mi[0]-m+mod)%mod,c[0][0]=1;
    for(int i=1;i<=m;i++)
        for(int j=c[i][0]=1;j<=i;j++)
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
    for(int i=1;i<=m;i++)
    {
        for(int j=(s[i]=1)-1;j<i;j++)
            (s[i]+=(lint)c[i][j]*s[j]%mod)%=mod;
        s[i]=(lint)t*(mi[i]-(lint)m*s[i]%mod+mod)%mod;
    }
    return !printf("%d\n",s[m]);
}

猜你喜欢

转载自blog.csdn.net/mys_c_k/article/details/79979447