BZOJ2272: [Usaco2011 Feb]Cowlphabet 奶牛文字

n<=250个大写字母和m<=250个小写字母,给p<=200个合法相邻字母,求用这些合法相邻字母的规则和n+m个字母能合成多少合法串,答案mod 97654321.

什么鬼膜数。。

f(i,j,k)--i个大写字母,j个小写字母,最后一个字母是k,,其中k是小写字母,p是能接在k前面的任意字母,k是大写字母的话同理。

这样复杂度是n*m*26*26?假的!i,j确定后只有p种合法转移,所以就n*m*p。

trick:记得算i=0和j=0的情况!!!

 1 #include<cstring>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 //#include<assert.h>
 5 //#include<time.h>
 6 #include<math.h>
 7 #include<algorithm>
 8 //#include<iostream>
 9 using namespace std;
10 
11 bool isdigit(char c) {return c>='0' && c<='9';}
12 int qread()
13 {
14     char c;int s=0,f=1;while (!isdigit(c=getchar())) f=(c=='-'?-1:1);
15     do s=s*10+c-'0'; while (isdigit(c=getchar())); return s*f;
16 }
17 
18 const int mod=97654321;
19 int da,xiao,m;
20 int f[255][255][55];
21 int id(char c) {return (c>='a' && c<='z')?c-'a':c-'A'+26;}
22 bool isalpha(char c) {return (c>='a' && c<='z') || (c>='A' && c<='Z');}
23 struct Edge{int to,next;}edge[255];int first[55],le=2;
24 void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;}
25 int main()
26 {
27     da=qread(),xiao=qread(),m=qread();
28     memset(first,0,sizeof(first));
29     for (int i=1;i<=m;i++)
30     {
31         char c1,c2;
32         while (!isalpha(c1=getchar()));
33         c2=getchar();
34         in(id(c2),id(c1));
35     }
36     for (int i=0;i<26;i++) f[0][1][i]=1,f[1][0][i]=0;
37     for (int i=26;i<52;i++) f[0][1][i]=0,f[1][0][i]=1;
38     for (int i=0;i<=da;i++)
39         for (int j=0;j<=xiao;j++) if (i+j>=2)
40         {
41             if (j) for (int now=0;now<26;now++)
42             {
43                 f[i][j][now]=0;
44                 for (int k=first[now];k;k=edge[k].next)
45                 {
46                     const Edge &e=edge[k];
47                     f[i][j][now]+=f[i][j-1][e.to],
48                     f[i][j][now]-=f[i][j][now]>=mod?mod:0;
49                 }
50             }
51             if (i) for (int now=26;now<52;now++)
52             {
53                 f[i][j][now]=0;
54                 for (int k=first[now];k;k=edge[k].next)
55                 {
56                     const Edge &e=edge[k];
57                     f[i][j][now]+=f[i-1][j][e.to],
58                     f[i][j][now]-=f[i][j][now]>=mod?mod:0;
59                 }
60             }
61         }
62     int ans=0;
63     for (int i=0;i<52;i++) ans+=f[da][xiao][i],ans-=ans>=mod?mod:0;
64     printf("%d\n",ans);
65     return 0;
66 }
View Code

 

posted @ 2017-10-26 19:15  Blue233333  阅读(202)  评论(0编辑  收藏  举报