题解 P5196 【[USACO19JAN]Cow Poetry】
简单的计数题
有题意得知,每一行都只关心最后一个词的韵部
所以前面的词可以随便乱填(好诗~)
规定
for(int j=0;j<=k;j++)
for(int i=1;i<=n;i++)
f[j+s[i]]+=f[j];
(直接复制可能会有一些小问题~)
然后再统计最后一个词的韵部的方案数
只要枚举单词给它空个位置就好啦
g[c[i]]+=f[k-s[i]]
然后就可以啦~
最后把每个韵部要求统计的行数都就求出来就好了
丑陋的代码
#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;
}