Pro 2 (cowlpha.pas/cpp/c)
题目描述:
像很多牛科动物一样,农夫John的奶牛会说一种特定的“牛语”。像很多语言一样,这种语言的每个单词包含一串大写或小写的字母 (A-Z以及a-z).一个单词是合法的当且仅当单词中每一对有序临近字母是合法的。
农夫John担心他的奶牛在预谋反对他,因而最近窃听了奶牛们的交流。他为了不被发现只偶然听到了一些单词,又因为”牛语”语速实在太快,所以农夫John实际只能分辨出一个单词里大写字母的总数(1≤U≤250)和小写字母总数(1≤L≤250).
输入格式:
第一行:3个由1个空格隔开的整数U,L,和P;
第2~p+1行:两个字母(每一个都有可能是大写或者小写),定义一对“牛语”合法有序临近对;
输出格式:
第一行:一个数,农夫John可能的听到的单词数,对97654321取模.
样例输入:
2 2 7
AB
ab
BA
ba
Aa
Bb
bB
样例输出:
7
样例解释:
AabB
ABba
abBA
BAab
BbBb
bBAa
bBbB
这题都能看出是dp吧
然后dp转移五花八门
我就说一下我的
表示前l位当前字母为i,大写字母数为j,小写字母数为 k 的方案数
第一维显然可以压掉
i1是i的前继,
,k1同理
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=255,P=97654321,D=52;
struct edge {
int t,next;
}e[10000];
int f[60][N][N],head[D+7],fa[D+7];
int read() {char c;while (c=getchar(),!(c>='a' && c<='z') && !(c>='A' && c<='Z'));if (c>='A' && c<='Z') return c-'A';else return c-'a'+26;}
int u,l,q,cnt,ans;
void add(int u,int t) {
e[++cnt].t=t;
e[cnt].next=head[u];
head[u]=cnt;
}
int main() {
freopen("cowlpha.in","r",stdin);
freopen("cowlpha.out","w",stdout);
scanf("%d%d%d",&u,&l,&q);
for (int i=1;i<=q;i++) {
int a=read(),b=read();
add(b,a);
}
for (int i=0;i<D;i++)
if (i<26) f[i][1][0]=1;
else f[i][0][1]=1;
for (int i=2;i<=u+l;i++) {
for (int j=min(i,u);j>=0;j--)
for (int k=min(i,l);k>=0;k--) {
if (j+k!=i) continue;
for (int h=0,j1,k1;h<D;h++) {
f[h][j][k]=0;
if (h<26 && j==0) continue;
if (h>=26 && k==0) continue;
if (h<26) j1=j-1,k1=k;
else j1=j,k1=k-1;
for (int z=head[h];z;z=e[z].next) {
int v=e[z].t;
f[h][j][k]=(f[h][j][k]+f[v][j1][k1])%P;
}
}
}
}
for (int i=0;i<D;i++) ans=(ans+f[i][u][l])%P;
printf("%d\n",ans);
}