hdu 5642 King's Order

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5642

题意:给出一个n,问一个长度为n的只含有小写字母的序列中,满足其中不含有超过3个连续相同字母的序列的个数有多少。

思路:

设dp[i][j],表示序列第i位为字母j的合法序列的个数。sum[i]表示长度为i的序列有多少个。

假设第i位为字母'a',dp[i][j]就是sum[i-1]*1-不合法的情况。

不合法的情况就是sum[i-4] - dp[i-4][j]。

sum[i-4]表示已经计算出的合法长度为i-4的序列个数,所以sum[i-4]*1*1*1表示第j-1,j-2,j-3的字母与第j位字母相同。

且因为sum[i-4]记录的是合法情况,在第j位之前不能出现连续4个相同字母,所以要再减去dp[i-4][j]。

所以可以得出dp[i][j] = sum[i-1] - (sum[i-4] - dp[i-4][j])

 

按三维的会更清楚一点 dp[i][j][k]表示当前第i位为字母‘a'+j且结尾字母已重复了k次的方案数有多少个。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const long long mod = 1000000007;
 6 int n;
 7 int T;
 8 long long dp[2010][30];
 9 long long sum[2010];
10 int main() 
11 {
12 //  freopen("in.txt", "r", stdin);
13     scanf("%d", &T);
14     
15     while(T--)
16     {
17         scanf("%d", &n);
18         memset(dp, 0, sizeof(dp));
19         memset(sum, 0, sizeof(sum));
20         for(int i = 0; i < 26; i++)
21         {
22             dp[1][i] = 1;
23         }
24         for(int i = 2; i <= n; i++)
25         {
26             for(int j = 0; j < 26; j++)
27             {
28                 sum[i-1] += dp[i-1][j];
29                 sum[i-1] %= mod;
30             }
31             for(int j = 0; j < 26; j++)
32             {
33                 if(i < 4) dp[i][j] = sum[i-1];
34                 else if(i == 4)
35                 {
36                     dp[i][j] = (sum[i-1]-1+mod)%mod; 
37                 }
38                 else if(i == 5)
39                 {
40                     dp[i][j] = (sum[i-1]-25+mod)%mod;
41                 }
42                 else
43                 {
44                     dp[i][j] = (sum[i-1]-(sum[i-4]-dp[i-4][j]+mod)%mod + mod)%mod;
45                 }
46             }
47         }
48         for(int i = 0; i < 26; i++)
49         {
50             sum[n] += dp[n][i];
51             sum[n] %= mod;
52         }
53        cout<<sum[n]<<endl; 
54     }
55     return 0;
56 }

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 long long dp[2010][30][5];
 4 int T;
 5 int n;
 6 const long long mod = 1000000007;
 7 int main() 
 8 {
 9   //  freopen("in.txt", "r", stdin);
10     scanf("%d", &T);
11     while(T--)
12     {
13         memset(dp, 0, sizeof(dp));
14         scanf("%d", &n);
15         for(int i = 0; i < 26; i++) dp[1][i][1] = 1;       
16         for(int i = 2; i <= n; i++)
17         {
18             long long temp = 0;
19             for(int j = 0; j < 26; j++)
20             {
21                 temp += dp[i-1][j][1]; temp %= mod;
22                 temp += dp[i-1][j][2]; temp %= mod;
23                 temp += dp[i-1][j][3]; temp %= mod;
24             }
25             for(int j = 0; j < 26; j++)
26             {
27                 long long temp2 = temp;
28                 temp2 = (temp2 - ((dp[i-1][j][1] + dp[i-1][j][2])%mod + dp[i-1][j][3])%mod + mod)%mod;
29                 dp[i][j][1] += temp2;  dp[i][j][1] %= mod;
30                 dp[i][j][2] += dp[i-1][j][1]; dp[i][j][2] %= mod;
31                 dp[i][j][3] += dp[i-1][j][2]; dp[i][j][3] %= mod;
32             }
33         }
34         long long sum = 0;
35         for(int i = 0; i < 26; i++)
36         {
37             sum = (sum + dp[n][i][1])%mod;
38             sum = (sum + dp[n][i][2])%mod;
39             sum = (sum + dp[n][i][3])%mod;
40         }
41         printf("%I64d\n", sum);
42     }
43     return 0;
44 }

 

posted @ 2016-03-12 22:02  下周LGD该赢了吧  阅读(221)  评论(0编辑  收藏  举报