Problem:
パスタ (Pasta)
問題
あなたはパスタが大好物であり，毎日，晩御飯にパスタを作って食べている．あなたはトマトソース，クリームソース，バジルソースの 3 種類のパスタを作ることができる．
N 日間の晩御飯の予定を考えることにした．それぞれの日に 3 種類のパスタから 1 種類を選ぶ．ただし，同じパスタが続くと飽きてしまうので，3 日以上連続して同じパスタを選んではいけない．また，N 日のうちの K 日分のパスタはすでに決めてある．
入力として N の値と，K 日分のパスタの情報が与えられたとき，条件をみたす予定が何通りあるかを 10000 で割った余りを求めるプログラムを作成せよ．
入力
入力は K + 1 行からなる．
1 行目には 2 つの整数 N, K (3 ≦ N ≦ 100，1 ≦ K ≦ N) が空白を区切りとして書かれている．
1 + i 行目 (1 ≦ i ≦ K) には 2 つの整数 A
i
, B
i
(1 ≦ A
i
≦ N，1 ≦ B
i
≦ 3) が空白を区切りとして書かれている．これは，A
i
日目のパスタはすでに決まっており，B
i
= 1 のときはトマトソースであり，B
i
= 2 のときはクリームソースであり，B
i
= 3 のときはバジルソースであることを表す．A
i
(1 ≦ i ≦ K) は全て異なる．与えられる入力データにおいて，条件をみたす予定は 1 通り以上あることが保証されている．
出力
条件をみたす予定が何通りあるかを 10000 で割った余りを 1 行で出力せよ．
入出力例
入力例 1
5 3
3 1
1 1
4 2
出力例 1
6
入出力例 1 において，あなたは 5 日間の予定を考える．1 日目と 3 日目はトマトソースであり，4 日目はクリームソースである．また，3 日以上連続して同じパスタを選んではいけない．これらの条件をみたす予定は 6 通りある．
1日目
2日目
3日目
4日目
5日目
予定 1
1
2
1
2
1
予定 2
1
2
1
2
2
予定 3
1
2
1
2
3
予定 4
1
3
1
2
1
予定 5
1
3
1
2
2
予定 6
1
3
1
2
3
この表では，1 はトマトソースを，2 はクリームソースを，3 はバジルソースを表す．
入力例 2
20 5
10 2
4 3
12 1
13 2
9 1
出力例 2
2640
入出力例 2 において，条件をみたす予定は全部で 4112640 通りある．それを 10000 で割った余りである 2640 を出力する．
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include <stdio.h>
#include <algorithm>
#include <string.h>
#define DAY_MAX	123
#define PASTA_MAX	5
#define ONAZI_MAX	123

int max;


int set_pasta[DAY_MAX];
int memo[DAY_MAX][PASTA_MAX][ONAZI_MAX];

int dp(int day, int pasta, int onazi){
	int numbuf = 0;
	int ans = 0;
	if (memo[day][pasta][onazi] >= 0) return memo[day][pasta][onazi];
	if (onazi == 3) return 0;
	if (day == max - 1) return 1;
	if (set_pasta[day + 1] >= 1){
		if (set_pasta[day + 1] == pasta) return memo[day][pasta][onazi] = dp(day + 1, pasta, onazi + 1);
		else return memo[day][pasta][onazi] = dp(day + 1, set_pasta[day + 1], 1);
	}
	else{
		for (int a = 0; a < 3; a++){
			if (a + 1 == pasta) ans += dp(day + 1, pasta, onazi + 1);
			else ans += dp(day + 1, a + 1, 1);
			ans %= 10000;
		}
		return ans;
	}
}

int main(){
	int num;
	int buf;
	int answer = 0;
	memset(memo, 255, sizeof(memo));
	scanf("%d%d", &max, &num);
	for (int a = 0; a < num; a++){
		scanf("%d", &buf);
		scanf("%d", &set_pasta[buf - 1]);
	}
	if (set_pasta[0] >= 1) printf("%d\n", dp(0, set_pasta[0], 1));
	else printf("%d\n", (dp(0, 1, 1) + dp(0, 2, 1) + dp(0, 3, 1)) % 10000);
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3000
final_rank: 1

code_snippet: #include<bits/stdc++.h>
#define rep(a,b) for(int a=0;a<b;a++)
#define int long long int

using namespace std;

const int INF = 1000000009;

int day,al;
int almost[200];
int ans=1;
int used[200];

int pasu(int p){
    if(p==3)return 1;
    else if(p==2)return 3;
    else if(p==1)return 2;
}

int pasu2(int p){
    if(p==3)return 2;
    else if(p==2)return 1;
    else if(p==1)return 3;
}

int kaburi1(int date){
    if(almost[date+1]!=0){
        return almost[date+1];
    }else return 0;
}

int kaburi2(int date){
    if(almost[date+2]!=0){
        return almost[date+2];
    }else return 0;
}

int pasuta(int d2, int d1, int dd1, int dd2,int date){
    if(date>day)return 1;
    else if(almost[date]!=0){
        return pasuta(d1,almost[date],kaburi1(date+1),kaburi2(date+1),date+1)%10000;
    }else if((d2==d1||d1==dd1)&&d1!=0){
       return (pasuta(d1,pasu(d1),kaburi1(date+1),kaburi2(date+1),date+1)+pasuta(d1,pasu2(d1),kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }else if(dd1==dd2&&dd1!=0){
        return (pasuta(d1,pasu(dd1),kaburi1(date+1),kaburi2(date+1),date+1)+pasuta(d1,pasu2(dd1),kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }else{
        return (pasuta(d1,1,kaburi1(date+1),kaburi2(date+1),date+1)+
        pasuta(d1,2,kaburi1(date+1),kaburi2(date+1),date+1)+
        pasuta(d1,3,kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }
}

signed main(){
    fill(almost,almost+200,0);
    fill(used,used+200,0);
    cin >> day >> al;
    rep(a,al){
        int da,pa;
        cin >> da >> pa;
        almost[da]=pa;
    }
    ans = pasuta(0,0,almost[2],almost[3],1);
    cout << ans%10000 << endl;
return 0;
}
accuracy: 0.2
time_ms: 1190
memory_kb: 1168
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define rep(a,b) for(int a=0;a<b;a++)
#define int long long int

using namespace std;

const int INF = 1000000009;

int day,al;
int almost[200];
int ans=1;
int used[200];

int pasu(int p){
    if(p==3)return 1;
    else if(p==2)return 3;
    else if(p==1)return 2;
}

int pasu2(int p){
    if(p==3)return 2;
    else if(p==2)return 1;
    else if(p==1)return 3;
}

int kaburi1(int date){
    if(almost[date+1]!=0){
        return almost[date+1];
    }else return 0;
}

int kaburi2(int date){
    if(almost[date+2]!=0){
        return almost[date+2];
    }else return 0;
}

int pasuta(int d2, int d1, int dd1, int dd2,int date){
    if(date>day)return 1;
    else if(almost[date]!=0){
        return pasuta(d1,almost[date],kaburi1(date+1),kaburi2(date+1),date+1)%10000;
    }else if((d2==d1||d1==dd1)&&d1!=0){
       return (pasuta(d1,pasu(d1),kaburi1(date+1),kaburi2(date+1),date+1)+pasuta(d1,pasu2(d1),kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }else{
        return (pasuta(d1,1,kaburi1(date+1),kaburi2(date+1),date+1)+
        pasuta(d1,2,kaburi1(date+1),kaburi2(date+1),date+1)+
        pasuta(d1,3,kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }
}

signed main(){
    fill(almost,almost+200,0);
    fill(used,used+200,0);
    cin >> day >> al;
    rep(a,al){
        int da,pa;
        cin >> da >> pa;
        almost[da]=pa;
    }
    ans = pasuta(0,0,almost[2],almost[3],1);
    cout << ans%10000 << endl;
return 0;
}
accuracy: 0.2
time_ms: 2620
memory_kb: 1160
final_rank: 4

code_snippet: #include<bits/stdc++.h>
#define rep(a,b) for(int a=0;a<b;a++)
#define int long long int

using namespace std;

const int INF = 1000000009;

int day,al;
int almost[200];
int ans=1;
int used[200];

int pasu(int p){
    if(p==3)return 1;
    else if(p==2)return 3;
    else if(p==1)return 2;
}

int pasu2(int p){
    if(p==3)return 2;
    else if(p==2)return 1;
    else if(p==1)return 3;
}

int kaburi1(int date){
    if(almost[date+1]!=0){
        return almost[date+1];
    }else return 0;
}

int kaburi2(int date){
    if(almost[date+2]!=0){
        return almost[date+2];
    }else return 0;
}

int pasuta(int d2, int d1, int dd1, int dd2,int date){
    if(date>day)return 1;
    //else if(used[date])return;
    else if(almost[date]!=0){
        //used[date]=1;
        return pasuta(d1,almost[date],kaburi1(date+1),kaburi2(date+1),date+1)%10000;
    }/*else if(d2==d1&&d1==dd1&&d1!=0){

        //used[date]=1;
//        cout << "a" << date;
       // if(d2==dd1){
            //ans=ans*2;
            return pasuta(dd1,dd2,kaburi1(date+3),kaburi2(date+3),date+3)+pasuta(dd1,dd2,kaburi1(date+3),kaburi2(date+3),date+3);
    //}else{
         //   return pasuta(dd1,dd2,kaburi1(date+3),kaburi2(date+3),date+3);
      //  }
    }*/else if((d2==d1||d1==dd1)&&d1!=0){
        //used[date]=1;

  //      cout << "b" << date;
        //ans=ans*2;
        return (pasuta(d1,pasu(d1),kaburi1(date+1),kaburi2(date+1),date+1)+pasuta(d1,pasu2(d1),kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }else{
      //  used[date]=1;
    //    cout << "c" << date;
        //ans=ans*3;
        return (pasuta(d1,1,kaburi1(date+1),kaburi2(date+1),date+1)+
        pasuta(d1,2,kaburi1(date+1),kaburi2(date+1),date+1)+
        pasuta(d1,3,kaburi1(date+1),kaburi2(date+1),date+1))%10000;
    }
}

signed main(){
    fill(almost,almost+200,0);
    fill(used,used+200,0);
    cin >> day >> al;
    rep(a,al){
        int da,pa;
        cin >> da >> pa;
        almost[da]=pa;
    }
    ans = pasuta(0,0,almost[2],almost[3],1);
    cout << ans << endl;
return 0;
}
accuracy: 0.2
time_ms: 2630
memory_kb: 1164
final_rank: 5

code_snippet: #include <iostream>
#include <sstream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
#include <string>
#include <cstring>

using namespace std;

#define int long long
#define LL long long
#define ULL unsigned long long

const LL LL_INF = ~(ULL)0 >> 1;

int day[105] = {0}, n, k, mem[101][4][4][4];

int f(int d, int src, int presrc, int num) {
    if (d == n) {
        return (num + 1) % 10000;
    }

    if (day[d + 1] != 0) {
        return f(d + 1, day[d + 1], src, num);
    }

    int result = num;
    for (int i = 1; i <= 3; ++i) {
        if (((presrc == src) && (presrc == i)) ||
                ((day[d + 2] != 0) && (src == i) && (i == day[d + 2]))) continue;

        //int temp = (mem[d + 1][i][src][presrc] == LL_INF) ? f(d + 1, i, src, 0) : mem[d + 1][i][src][presrc];
        int temp = f(d + 1, i, src, 0);
        mem[d + 1][i][src][presrc] = temp;
        result = (result + temp) % 10000;
    }

    return result;
}

signed main() {
    for (int i = 0; i < 101; ++i) {
        for (int j = 0; j < 4; ++j) {
            for (int k = 0; k < 4; ++k) {
                fill(mem[i][j][k], mem[i][j][k] + 4, LL_INF);
            }
        }
    }
    cin >> n >> k;

    for (int i = 0; i < k; ++i) {
        int a, b;
        cin >> a >> b;
        day[a] = b;
    }

    int result = 0;

    if (day[1] == 0) {
        for (int i = 1; i <= 3; ++i) {
            result = (result + f(1, i, 0, 0)) % 10000;
        }
    } else {
        result = (result + f(1, day[1], 0, 0)) % 10000;
    }

    cout << result << endl;

    return 0;
}
accuracy: 0.2
time_ms: 1190
memory_kb: 1208
final_rank: 3