动态规划训练之十一
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;
}