Problem:
問題 4:　部活のスケジュール表 (Schedule)
問題
IOI 高校のプログラミング部には，J 君と O 君と I 君の 3 人の部員がいる．
プログラミング部では，部活のスケジュールを組もうとしている．
今，N 日間の活動のスケジュールを決めようとしている．
各活動日のスケジュールとして考えられるものは，各部員については活動に参加するかどうかの 2 通りがあり，部としては全部で 8 通りある．
部室の鍵はただ 1 つだけであり，最初は J 君が持っている．
各活動日には，その日の活動に参加する部員のうちのいずれか 1 人が鍵を持っている必要があり，活動後に参加した部員のいずれかが鍵を持って帰る．
プログラミング部では，活動日には毎回必ず活動が行われるように，あらかじめ各活動日の責任者を定めた．
責任者は，必ずその日の活動に出席しなければならない．
スケジュールを決めようとしている日数と，各活動日の責任者が誰であるかの情報が与えられた時，すべての活動日に部活動を行うことができるようなスケジュール表として考えられるものの数を 10007 で割った余りを求めるプログラムを作成せよ．
ただし，部活の終了時に鍵を持って帰る部員は，その日の活動に参加している部員の誰でもよく，最終日は誰が鍵を持って帰ってもよいものとする．
入力
入力は，2 行からなる．
1 行目には，スケジュールを決めようとしている日数を表す 1 つの整数 N (2 ≤ N ≤ 1000) が書かれている．
2 行目には，各活動日の責任者を表す N 文字からなる文字列が書かれている．
この文字列の i 文字目 (1 ≤ i ≤ N) は，i 日目の活動日の責任者を表す．
すなわち，i 文字目が J, O, I であることはそれぞれ i 日目の活動日の責任者が J 君，O 君，I 君であることを意味する．
出力
スケジュール表として考えられるものの数を 10007 で割った余りを 1 行で出力せよ．
入出力例
入力例 1
2
OI
出力例 1
7
入出力例 1 において，2 日間の活動日のスケジュールを考える．1 日目の責任者は O 君，2 日目の責任者は I 君である．
問題文の条件をみたすスケジュール表は 7 通り考えられる．
1 日目
2 日目
スケジュール 1
J, O
O, I
スケジュール 2
J, O
J, I
スケジュール 3
J, O
J, O, I
スケジュール 4
J, O, I
I
スケジュール 5
J, O, I
J, I
スケジュール 6
J, O, I
O, I
スケジュール 7
J, O, I
J, O, I
この表では，J, O, I はそれぞれその日に J 君, O 君, I 君が参加することを表す．
1 日目の責任者は O 君であるが，最初鍵を持っているのは J 君であるため，1 日目の活動には J 君, O 君の両方が参加する必要があることに注意せよ．
また，1 日目に鍵を持って帰った人は 2 日目にも参加しないといけないので，1 日目と 2 日目の両方に参加する人が少なくとも 1 人存在しなければならないことに注意せよ．
入力例 2
20
JIOIJOIJOJOIIIOJIOII
出力例 2
4976
入出力例 2 において，条件をみたすスケジュール表は全部で 72493594992 通り考えられる．それを 10007 で割った余りである 4976 を出力する．
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string p[7]={"J","O","I","JI","JO","IO","JOI"};
int dp[1001][7]={{0},{0}};
int d;string s;//d日、s責任者

bool ok(int a,int b,char c){
	string f=p[a],se=p[b];
	bool flag1=false,flag2=false;
	for(int i=0;i<se.size();i++){
		if(se[i]==c)flag1=true;
	}
	for(int i=0;i<f.size();i++){
		for(int j=0;j<se.size();j++){
			if(f[i]==se[j])flag2=true;
		}
	}
	if(flag1&&flag2)return true;
	else return false;
}
int main(){
	cin>>d>>s;
	for(int i=0;i<7;i++)(ok(0,i,s[0]))?dp[0][i]=1:dp[0][i]=0;
//	for(int j=0;j<7;j++)if(ok(4,j,s[1]))dp[1][j]+=1;
	//	for(int j=0;j<7;j++)if(ok(6,j,s[1]))dp[1][j]+=1;
	
	for(int i=0;i<d-1;i++){
		for(int j=0;j<7;j++){//i+1日目のjパターン
			int x=0;
			for(int k=0;k<7;k++){//i日目
				if(ok(k,j,s[i+1])&&dp[i][k])dp[i+1][j]=(dp[i+1][j]+dp[i][k])%10007;
			}
		}
	}
	
	/*for(int i=0;i<d;i++){
	for(int j=0;j<7;j++)cout<<dp[i][j]<<" ";
	cout<<endl;
	}*/
	int ans=0;
	for(int i=0;i<7;i++)ans+=dp[d-1][i];
	cout<<ans%10007<<endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 1248
final_rank: 1

code_snippet: #include<iostream>
//j=前の日,1=J,11=JO,111=JOI,100=I
using namespace std;
int n, ho[1202] = {} ,memo[112][1001][112];
char a[1202];
int sh(int j, int day,int ij)
{
	int A = 0;
	A = j - ho[day];
	if (A == 99 || A == 9 || A == 109 || A == 90 || A == 91 || A == -9 || A == -99 || A == -90 || A == -89)return 0;
	int B;
	B = j - ij;
	if (ij == 11)
	{
		if (j == 110)
			B=1000;
		if (j == 101)
			B=1000;
	}
	if (ij == 110 ){
		if (j==11)
		B = 1000;
		if (j == 101)
			B = 1000;
	}
	if (ij == 101 ){
		if (j==110)
		B = 1000;
		if (j == 11)
			B = 1000;
	}
	
	if (B == 9 || B == 99 || B == 109 || B == -9 || B == 90 || B == 91 || B == 89 || B == -99 || B == -90 || B == -89 || B == -109 || B == -91){
		return 0;
	}
	if (day > n)return 0;

	if (day == n)return 1;


	int ans = 0;
	if (memo[j][day][ij] != -1){
		return  memo[j][day][ij]; 
	} else{
	
	ans += sh(1, day + 1, j);
	ans += sh(11, day + 1, j);
	ans += sh(10, day + 1, j);
	ans += sh(100, day + 1, j);
	ans += sh(110, day + 1, j);
	ans += sh(111, day + 1, j);
	ans += sh(101, day + 1, j);
	}
	ans%=10007;
	memo[j][day][ij] = ans;
	return ans;
}
int main()
{
	int s[2500] = {};
	cin >> n;
	cin >> a;
	ho[0] = 1;
	for (int i = 0; i < n; i++)
	{
		if (a[i] == 'J')ho[i+1] = 1;
		if (a[i] == 'O')ho[i+1] = 10;
		if (a[i] == 'I')ho[i+1] = 100;
	}
	for (int i = 0; i < 112; i++)
	{
		for (int g = 0; g < 1001; g++)
		{
			for (int jk = 0; jk < 112; jk++)
			{
				memo[i][g][jk] = -1;
			}
			
		}
	}

	cout << sh(1,0,0) << endl;

	return 0;
}





/*#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;

string moji,yoso[200];

int f(string a)
{
	if(moji.find(a,0))
	{
		
}
int main ()
{
	int z;
	int ans=0;
	cin>>z;
	cin>>moji;
	for(int i=0;i<z;i++)
	{
		cin>>yoso[i];
		
	}
	for(int i=0;i<z;i++)
	{
		if(moji.find(yoso[i],0)){ans++;continue;}
		f(yoso[i].at(0));
	}
	return 0;
}*/
accuracy: 1
time_ms: 10
memory_kb: 50280
final_rank: 2

code_snippet: #include<iostream>
//j=前の日,1=J,11=JO,111=JOI,100=I
using namespace std;
int n, ho[2500] = {} ,memo[2500][2500];
char a[2500];
int sh(int j, int day)
{
	int A = 0;
	A = j - ho[day];
	if (A == 99 || A == 9 || A == 109 || A == 90 || A == 91 || A == -9 || A == -99 || A == -90 || A == -89)return 0;
	if (day > n)return 0;

	if (day == n)return 1;

	//if (memo[j][ho[day]] != -1)return memo[j][ho[day]];



	int ans = 0;

	if (j == 1){
		ans += sh(1, day + 1);
		ans += sh(11, day + 1);
	//	ans += sh(10, day + 1);
	//	ans += sh(100, day + 1);
	//	ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		ans += sh(101, day + 1);
	}
	else if (j == 10)
	{
		//ans += sh(1, day + 1);
		ans += sh(11, day + 1);
		ans += sh(10, day + 1);
		//ans += sh(100, day + 1);
		ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		//ans += sh(101, day + 1);
	}
	else if (j==11)
	{
		ans += sh(1, day + 1);
		ans += sh(11, day + 1);
		ans += sh(10, day + 1);
		//ans += sh(100, day + 1);
		ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		ans += sh(101, day + 1);
	}
	else if (j==100)
	{
	//	ans += sh(1, day + 1);
	//	ans += sh(11, day + 1);
	//	ans += sh(10, day + 1);
		ans += sh(100, day + 1);
		ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		ans += sh(101, day + 1);
	}
	else if (j==110)
	{
	//	ans += sh(1, day + 1);
		ans += sh(11, day + 1);
		ans += sh(10, day + 1);
		ans += sh(100, day + 1);
		ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		ans += sh(101, day + 1);
	}
	else if (j==111)
	{
		ans += sh(1, day + 1);
		ans += sh(11, day + 1);
		ans += sh(10, day + 1);
		ans += sh(100, day + 1);
		ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		ans += sh(101, day + 1);
	}
	else if (j==101)
	{
		ans += sh(1, day + 1);
		ans += sh(11, day + 1);
	//	ans += sh(10, day + 1);
		ans += sh(100, day + 1);
		ans += sh(110, day + 1);
		ans += sh(111, day + 1);
		ans += sh(101, day + 1);
	}

	memo[j][ho[day]] = ans;
//	ans %= 10007;
//	return memo[j][ho[day]]=ans;
	return ans;
}
int main()
{
	int s[2500] = {};
	cin >> n;
	cin >> a;
	ho[0] = 1;
	for (int i = 0; i < n; i++)
	{
		if (a[i] == 'J')ho[i+1] = 1;
		if (a[i] == 'O')ho[i+1] = 10;
		if (a[i] == 'I')ho[i+1] = 100;
	}
	for (int i = 0; i < 2500; i++)
	{
		for (int g = 0; g < 2500; g++)
		{
			memo[i][g] = -1;
		}
	}

	cout << sh(1,0) << endl;

	
	int hjhj;
	cin >> hjhj;
	return 0;
}
/*
int A;
if (day > n)return 0;
if (day == 1){
if (j == 10 || j == 100 || j == 110)return 0;
}
if (day != 0)
{
A = j - ho[day - 1];
if (A == 99 || A == 9 || A == 109 || A == 90 || A == 91 || A == -9 || A == -99 || A == -90 || A == -89)return 0;
}
if (day == n)return 1;
int ans = 0;
if (memo[j][ho[day-1]] != -1)return memo[j][ho[day-1]];
*/
accuracy: 0.2
time_ms: 1440
memory_kb: 25584
final_rank: 3