动态规划训练之十一

https://www.luogu.org/problem/P5196

开始那道题会觉得计数很棘手,思考一番

这个背包dp式子很好得出

if(dp[j])

dp[j+len[i]]+=dp[j];

但是这是没有最后一个单词的前提下才行

那怎么办?(不会就dp)--->>很有用的

f[col[i]]+=dp[k-col[i]];

表示押韵col的最后一个放置的方案数

x个压Y韵的方案数就为ksm(f[y],x)快速幂

最后将不同的押韵方案数累加起来就好

code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 5005
using namespace std;
typedef long long LL;
int n,m,k;
LL s[N],c[N];
LL f[N],g[N];
LL nd[30];
const LL mod=1000000007;
LL ksm(LL b,LL k)
{
    if(k==0) return 1;
    if(k==1) return b%mod;
    LL q=ksm(b,k>>1);
    if(k&1) return q*q%mod*b%mod;
    else return q*q%mod;
}
bool cmp(LL x,LL y)
{
    return x>y;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&s[i],&c[i]);
    f[0]=1;
    for(int j=0;j<=k;j++)
    if(f[j]) 
        for(int i=1;i<=n;i++)
            if(j+s[i]<=k)   f[j+s[i]]=(f[j+s[i]]+f[j])%mod;
    for(int i=1;i<=n;i++)
        g[c[i]]=(g[c[i]]+f[k-s[i]])%mod;
    while(m--)
    {
        char s[5];
        scanf("%s",s);
        nd[s[0]-'A']++;
    }
    sort(nd,nd+26,cmp);
    sort(g+1,g+n+1,cmp);
    LL ans=1;
    for(int i=0;i<26&&nd[i];i++)
    {
        LL x=nd[i],sum=0;
        for(int j=1;j<=n&&g[j];j++)
            sum=(sum+ksm(g[j],x))%mod;
        ans=ans*sum%mod;    
    }
    printf("%lld\n",ans);
    return 0;
} 
posted @ 2019-10-11 19:22  wzx_believer  阅读(80)  评论(0编辑  收藏  举报