题目链接: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])
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 }
hdu 5642 King's Order
时间: 2024-10-07 02:15:58