题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5642
题意:一个长度为n的序列,并且序列中不能出现长度大于3的连续的相同的字符,求一共有多少个合法序列。
思路:用dp[i][j]表示以j结尾,长度为i的合法序列个数。我们考虑一下这个怎么转移。
以j结尾的话就三种情况,一个j结尾,两个j结尾,三个j结尾。如果是三个j结尾的话我们可以确定下来,长度为i的后三位是j,倒数第4位不可以是j,所以就是∑dp[i-3][k](k!=j),同理考虑两个j结尾和一个j结尾,那么转移方程就是:dp[i][j] = ∑dp[i-1][k] + ∑dp[i-2][k] + ∑dp[i-3][k]
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 1000000007
int dp[2005][26];
int T;
int n;
int ans;
void init()
{
Clean(dp,0);
rep(i,0,25) //前三位没有非法序列,先手写上
{
dp[1][i] = 1;
dp[2][i] = 26;
dp[3][i] = 676;
}
rep(i,4,2000)
{
if ( i > 3 )
rep(j,0,25)
rep(k,0,25)
{
if ( j == k ) continue;
dp[i][j] = ( dp[i][j] + dp[i-3][k] ) % mod;
}
if ( i > 2 )
rep(j,0,25)
rep(k,0,25)
{
if ( j == k ) continue;
dp[i][j] = ( dp[i][j] + dp[i-2][k] ) % mod;
}
if ( i > 1 )
rep(j,0,25)
rep(k,0,25)
{
if ( j == k ) continue;
dp[i][j] = ( dp[i][j] + dp[i-1][k] ) % mod;
}
}
}
int main()
{
init();
cin>>T;
while(T--)
{
scanf("%d",&n);
ans = 0;
rep(i,0,25) ans = ( ans + dp[n][i] ) % mod;
printf("%d\n",ans);
}
return 0;
}