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; }