题目链接: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 ", sum); 42 } 43 return 0; 44 }