トップページに戻る    次の競技プログラミングの問題へ    前の競技プログラミングの問題へ

ABC-071-D Coloring Dominoes

■■■問題■■■

2×Nのマス目があります。
すぬけ君は、このマス目にN個のドミノを、重ならないように敷き詰めました。
ここで、ドミノは、1×2または2×1のマス目を覆うことができます。

すぬけ君は、赤色、水色、緑色の3色を使って、これらのドミノを塗ることにしました。
このとき、辺で接しているドミノは異なる色で塗るようにします。
ここで、必ずしも3色すべてを使う必要はありません。

このような塗り方が何通りあるかを mod 1000000007 で求めてください。

ただし、ドミノの敷き詰め方は、文字列S1,S2を用いて、次のようにして与えられます。
●各ドミノは、それぞれ異なる英小文字または英大文字で表される。
●Siのj文字目は、マス目の上からi番目、左からj番目のマスにどのドミノがあるかを表す。

■■■入力■■■

N
S1
S2

●1 <= N <= 52
●|S1| = |S2| = N
●S1,S2 は英小文字または英大文字からなる
●S1,S2 は正しいドミノの敷き詰め方を表している

■■■出力■■■

ドミノを塗る方法の数を mod 1000000007 で出力せよ。

■■■サンプルケースのイメージ■■■

■入出力例1のイメージ■
次の6通りあります



C#のソース

using System;
using System.Collections.Generic;

class Program
{
    static string InputPattern = "Input1";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("3");
            WillReturn.Add("aab");
            WillReturn.Add("ccb");
            //6
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("1");
            WillReturn.Add("Z");
            WillReturn.Add("Z");
            //3
            //必ずしもすべての色を使わなくてもよいことに注意してください
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("52");
            WillReturn.Add("RvvttdWIyyPPQFFZZssffEEkkaSSDKqcibbeYrhAljCCGGJppHHn");
            WillReturn.Add("RLLwwdWIxxNNQUUXXVVMMooBBaggDKqcimmeYrhAljOOTTJuuzzn");
            //958681902
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();
        string S1 = InputList[1];
        string S2 = InputList[2];

        int UB_X = S1.Length - 1;
        int UB_Y = 1;

        char[,] BanArr = new char[UB_X + 1, UB_Y + 1];
        for (int LoopX = 0; LoopX <= UB_X; LoopX++) {
            for (int LoopY = 0; LoopY <= UB_Y; LoopY++) {
                if (LoopY == 0) BanArr[LoopX, 0] = S1[LoopX];
                if (LoopY == 1) BanArr[LoopX, 1] = S2[LoopX];
            }
        }

        //横に配置をX、縦に配置をY、として文字列で持つ
        var HaitiList = new List<char>();
        for (int LoopX = 0; LoopX <= UB_X; ) {
            if (BanArr[LoopX, 0] != BanArr[LoopX, 1]) {
                HaitiList.Add('X');
                LoopX += 2;
            }
            else {
                HaitiList.Add('Y');
                LoopX++;
            }
        }

        long Answer = 1;
        for (int I = 0; I <= HaitiList.Count - 1; I++) {
            char CurrHaiti = HaitiList[I];

            if (I == 0) {
                Answer = (CurrHaiti == 'X' ? 6 : 3);
            }
            else {
                char PrevHaiti = HaitiList[I - 1];
                if (PrevHaiti == 'X' && CurrHaiti == 'X') Answer *= 3;
                if (PrevHaiti == 'X' && CurrHaiti == 'Y') Answer *= 1;
                if (PrevHaiti == 'Y' && CurrHaiti == 'X') Answer *= 2;
                if (PrevHaiti == 'Y' && CurrHaiti == 'Y') Answer *= 2;
            }
            Answer %= 1000000007;
        }
        Console.WriteLine(Answer);
    }
}


解説

ドミノを横に配置するならX
ドミノを縦に配置するならY
として、配置の仕方を求めておき、
1番左から配置ごとの場合の数で、積の法則を使ってます。