hdu 6143 Killer Names dp

来源:互联网 发布:创意美工设计招聘 编辑:程序博客网 时间:2024/05/21 17:33

                                                题 目 传 送 门:

题意:给出一个m个字母的字母表,问我们能生成多少对字符串,该对字符串长度为n。并且字符串之间不能存在相同的字母


思路1:用容斥原理推出状态转移方程dp[i][j]=dp[i-1][j]*i+dp[i-1][j-1]*i;

ac代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const long long mod=1e9+7;long long C[2005][2005];long long dp[2005][2005];long long m,n;void get_C(){    C[0][0] = 1;    for(int i=1;i<=2000;i++)    {        C[i][0] = 1;        for(int j=1;j<=i;j++)        C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;    }}long long quickmod(long long a,long long b){    long long ans=1;    a%=mod;    while(b>0)    {        if(b%2==1)        ans=ans*a%mod;        a=a*a%mod;        b/=2;    }    return ans;}void get_dp(){    for(int i=1;i<=2000;i++)    dp[i][1]=1;    for(long long i=2;i<=2000;i++)    {        for(long long j=i;j<=2000;j++)        {            dp[j][i]=((dp[j-1][i]*i)%mod+(dp[j-1][i-1]*i)%mod)%mod;        }    }}int main(){    int t;    get_C();    get_dp();    scanf("%d",&t);    while(t--)    {        scanf("%lld%lld",&n,&m);        long long ans=0;        for(long long i=1;i<m;i++)        {            if(i>n)break;            for(long long j=i;j+i<=m;j++)            {            if(j>n)break;            long long p=C[m][i]*dp[n][i]%mod;            long long q=C[m-i][j]*dp[n][j]%mod;            long long sum=(p*q)%mod;            if(j!=i)            ans=(ans+2*sum)%mod;            else            ans=(ans+sum)%mod;            }        }        printf("%lld\n",ans);    }    return 0;}


思路2:dp[i][j]表示用j中颜色去涂i个格子(j中颜色全用上),然后直接dp。状态转移方程为:dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1]*(m-(j-1));


ac代码:

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int mod = 1e9 + 7;const int maxn = 2010;ll dp[maxn][maxn];ll quick_pow(ll a, ll n) {    ll ans = 1;    while (n) {        if (n & 1)    ans = ans*a%mod;        a = a*a%mod;        n >>= 1;    }    return ans;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,m;        scanf("%d%d",&n,&m);        dp[1][1]=m;        for(int i=2;i<=n;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 ans=0;        for(int i=1;i<m;i++)        {            ans=(ans+dp[n][i]*quick_pow(m-i,n)%mod)%mod;        }        printf("%lld\n",ans);    }    return 0;}

 
原创粉丝点击