hihoCoder编程练习赛10 出勤记录II

题目来源
http://hihocoder.com/contest/offers10/problem/2
描述
小Hi的算法课老师每次上课都会统计小Hi的出勤记录。迟到会被记录一个L,缺席会被记录一个A,按时上课会被记录一个O。
一学期结束,小Hi的出勤记录可以看成是一个只包含LAO的字符串,例如"OOOOLOOOLALLO……"。
如果小Hi整学期缺席不超过1次,并且没有连续3次迟到,小Hi的出勤记录就算合格。  
现在给出字符串的长度N,小Hi想知道长度为N的出勤记录中,合格的记录总共有多少种。  
例如长度为3的合格出勤记录有19种:OOO OOL OOA OLO OAO LOO AOO OLL OLA OAL LOL LOA AOL LLO LAO ALO LLA LAL ALL。
输入
一个整数N(1 <= N <= 100000)。
输出
长度为N的合格记录总数。由于结果可能很大,你只需输出结果模10e9+7的余数。
样例输入
3
样例输出
19
分析
好久没写编程题,一开始没想到好的解决方法。
没有好的想法时,dp往往会是解法。
首先考虑的是用n*3的数组存储数据,但是分析后发现对于A没法处理。于是采用n*7的数组,见代码。

代码

#include 
using namespace std;
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//#pragma comment(linker, "/STACK:102400000,102400000")
#define EACH(it,a) for(auto it=begin(a);it!=end(a);it++)
#define ALL(a) a.begin(),a.end()
#define MEMA0(a) memset(a,0,sizeof(a))
#define SI(x) ((int)(x).size())
templateT GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
#define LL long long
typedef double DB;
typedef vector VI;
#define INF 0x3f3f3f3f
const int    MOD = int(1e9) + 7;
const double EPS = 1e-9;
const int    SZ = 100002;

LL dp[SZ][7];

int main()
{
	ios_base::sync_with_stdio(0);
#ifdef LJY
	//freopen("in.txt", "r", stdin);
#endif
	int i, j;
	int n;
	cin >> n;
	dp[0][5] = 1;
	for (i = 1; i <= n; i++) {
		//L1    (当前为L,且之前一个不是L,且之前不包含A
		dp[i][0] = (dp[i - 1][5]) % MOD;
		//L1(A) (当前为L,且之前一个不是L,且之前包含A
		dp[i][1] = (dp[i - 1][4] + dp[i - 1][6]) % MOD;
		//L2    (当前为L,且之前一个是L,且之前不包含A
		dp[i][2] = (dp[i - 1][0]) % MOD;
		//L2(A)
		dp[i][3] = (dp[i - 1][1]) % MOD;
		//A
		dp[i][4] = (dp[i - 1][0] + dp[i - 1][2] + dp[i - 1][5]) % MOD;
		//O
		dp[i][5] = (dp[i - 1][0] + dp[i - 1][2] + dp[i - 1][5]) % MOD;
		//O(A)
		dp[i][6] = (dp[i - 1][1] + dp[i - 1][3] + dp[i - 1][4]+ dp[i - 1][6]) % MOD;
	}
	LL ans = 0;
	for (j = 0; j < 7; j++)
		ans += dp[n][j];
	cout << ans % MOD;

	return 0;
}



你可能感兴趣的:(ACM)