HDU 6143 Killer Names(容斥+组合)

来源:互联网 发布:nba2k17mc捏脸数据 编辑:程序博客网 时间:2024/05/16 11:26
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;/*容斥+组合有m个字符,两个长度为n的空串,要使两个长为n的空串填满,并且两个空串不出现相同的字符,问有多少种填法。*/typedef long long LL;const int mod=1e9+7;const int maxn=2e3+5;LL c[maxn][maxn];LL p[maxn][maxn];void init(){    for(int i=0; i<maxn; i++)//预处理组合数    {        c[i][0]=1;        for(int j=1; j<=i; j++)        {            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;        }    }    for(int i=0;i<maxn;i++)    {        p[0][i]=0;    }    for(int i=1;i<maxn;i++)//预处理(i^j)    {        p[i][0]=1;        for(int j=1;j<maxn;j++)        {            p[i][j]=(p[i][j-1]*i)%mod;        }    }}LL pow_mod(LL a, LL b,LL mod){    LL res = 1;    a %= mod;    while(b)    {        if(b & 1)        {            res = res * a % mod;            b--;        }        b >>= 1;        a = a * a % mod;    }    return res;}int main(){    int n,m;    int T;    init();    scanf("%d",&T);    while(T--)    {        scanf("%d %d",&n,&m);        LL ans=0;        LL tmp;//第一串可能的情况        LL rc;//用于容斥        for(int i=1;i<=min(n,m-1);i++)//选出i个字符用于第一串填充        {            tmp=0;            rc=1;            for(int j=i;j>=1;j--)//计算第一串排列情况            {                tmp=(tmp+c[i][j]*rc*p[j][n]%mod)%mod;                rc*=-1;            }            //cout<<"tmp="<<tmp<<endl;            ans=(ans+tmp*c[m][i]%mod*p[m-i][n]%mod)%mod;            //p[m-i][n]为第二串排列情况        }        printf("%I64d\n",(ans%mod+mod)%mod);    }    return 0;}
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;/*dp+组合有m个字符,两个长度为n的空串,要使两个长为n的空串填满,并且两个空串不出现相同的字符,问有多少种填法。*/typedef long long LL;const int mod=1e9+7;const int maxn=2e3+5;int n,m;LL dp[maxn][maxn];void init(){    dp[1][1]=m;    for(int i=2;i<=n;i++)//选择j个字母用来填充i个位置的方案    {        for(int j=1;j<=i&&j<=m;j++)//由两种状态转移而来        {            dp[i][j]=(dp[i-1][j]*j%mod+dp[i-1][j-1]*(m-j+1)%mod)%mod;        }    }}LL pow_mod(LL a, LL b,LL mod){    LL res = 1;    a %= mod;    while(b)    {        if(b & 1)        {            res = res * a % mod;            b--;        }        b >>= 1;        a = a * a % mod;    }    return res;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d %d",&n,&m);        init();        LL ans=0;        for(int i=1;i<m;i++)//选择i个字符填充第一个串        {            ans=(ans+dp[n][i]*pow_mod(m-i,n,mod)%mod)%mod;        }        printf("%I64d\n",(ans%mod+mod)%mod);    }    return 0;}
原创粉丝点击