/**//* 目标串是有U个大写字母,L个小写字母 给出P个合法的字母对(a,b) 表示目标串相邻的字母必满足这些字母对,不能由其他组成 问有多少种可能的目标串 U,L <= 250 P <= 200
我比较土,总共52个字母,建立52个点的图 状态是(pos, u, l) 在点pos处,还剩下u个大写,l个小写的总数 其实O(ULP)的dp即可 (我之前也有想过的,但是转移我居然是枚举字母来转移52*52,然后就放弃了) 转移应该是枚举字母对!!! 总共P个
*/ #include<iostream> #include<cstring> #include<map> #include<algorithm> #include<stack> #include<queue> #include<cmath> #include<string> #include<cstdlib> #include<vector> #include<cstdio> #include<set> #include<list> #include<numeric> #include<cassert> #include<ctime>
using namespace std;
const int MOD = 97654321;
char validPair[201][3]; int dp[251][251][52];
inline int get(char ch){ return isupper(ch) ? 26+ch-'A' : ch-'a'; }
int main() { #ifndef ONLINE_JUDGE freopen("in","r",stdin); #endif
for(int U, L, P; ~scanf("%d%d%d", &U, &L, &P); ){ for(int i = 0 ; i < P ; i++){ scanf("%s", validPair[i]); //先get完,后面在计算时就不用再次get快很多 validPair[i][0] = get(validPair[i][0]); validPair[i][1] = get(validPair[i][1]); } memset(dp, 0, sizeof dp); for(int j = 0 ; j < 52 ; j++){ dp[(j>=26)][(j<26)][j] = 1; } for(int u = 0 ; u <= U ; u ++){ for(int l = 0; l <= L ; l++){ if(u+l <= 1){ continue; } for(int i = 0; i < P ; i++){ int first = validPair[i][0]; int second = validPair[i][1]; if(second < 26 && l > 0){ dp[u][l][second] += dp[u][l-1][first]; dp[u][l][second] %= MOD; } if(second >= 26 && u > 0){ dp[u][l][second] += dp[u-1][l][first]; dp[u][l][second] %= MOD; }
} } } printf("%lld\n", accumulate(dp[U][L], dp[U][L]+52, 0LL) % MOD); } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|