codeforces863C 1-2-3

C. 1-2-3
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Ilya is working for the company that constructs robots. Ilya writes programs for entertainment robots, and his current project is "Bob", a new-generation game robot. Ilya's boss wants to know his progress so far. Especially he is interested if Bob is better at playing different games than the previous model, "Alice".

So now Ilya wants to compare his robots' performance in a simple game called "1-2-3". This game is similar to the "Rock-Paper-Scissors" game: both robots secretly choose a number from the set {1, 2, 3} and say it at the same moment. If both robots choose the same number, then it's a draw and noone gets any points. But if chosen numbers are different, then one of the robots gets a point: 3 beats 2, 2beats 1 and 1 beats 3.

Both robots' programs make them choose their numbers in such a way that their choice in (i + 1)-th game depends only on the numbers chosen by them in i-th game.

Ilya knows that the robots will play k games, Alice will choose number a in the first game, and Bob will choose b in the first game. He also knows both robots' programs and can tell what each robot will choose depending on their choices in previous game. Ilya doesn't want to wait until robots play all k games, so he asks you to predict the number of points they will have after the final game.

Input

The first line contains three numbers kab (1 ≤ k ≤ 1018, 1 ≤ a, b ≤ 3).

Then 3 lines follow, i-th of them containing 3 numbers Ai, 1, Ai, 2, Ai, 3, where Ai, j represents Alice's choice in the game if Alice chose i in previous game and Bob chose j (1 ≤ Ai, j ≤ 3).

Then 3 lines follow, i-th of them containing 3 numbers Bi, 1, Bi, 2, Bi, 3, where Bi, j represents Bob's choice in the game if Alice chose i in previous game and Bob chose j (1 ≤ Bi, j ≤ 3).

Output

Print two numbers. First of them has to be equal to the number of points Alice will have, and second of them must be Bob's score after kgames.

Examples
input
10 2 1
1 1 1
1 1 1
1 1 1
2 2 2
2 2 2
2 2 2
output
1 9
input
8 1 1
2 2 1
3 3 1
3 1 3
1 1 1
2 1 1
1 2 3
output
5 2
input
5 1 1
1 2 2
2 2 2
2 2 2
1 2 2
2 2 2
2 2 2
output
0 0
Note

In the second example game goes like this:

The fourth and the seventh game are won by Bob, the first game is draw and the rest are won by Alice.

 找循环节,然后复杂度就是O(1)了。。。

(因为A, B的状态一共有9种,所以就是O(1))

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <map>
#include <vector>
#include <cassert>

using namespace std;

typedef unsigned long long int ulli;

typedef pair<ulli, ulli> DULLI;

ulli k, a, b, A[5][5], B[5][5];

// dfn[i][j] : 状态i, j的clock值
ulli dfn[5][5];

// val[i][j] : A, B在i, j时候的前缀值
DULLI val[5][5];

// 返回A, B的当前得分
DULLI get(ulli a, ulli b) {
    if(a == 1) {
        if(b == 1) {
            return make_pair(0, 0);
        } else if(b == 2) {
            return make_pair(0, 1);
        } else if(b == 3){
            return make_pair(1, 0);
        }
    } else if(a == 2) {
        if(b == 1) {
            return make_pair(1, 0);
        } else if(b == 2) {
            return make_pair(0, 0);
        } else if(b == 3){
            return make_pair(0, 1);
        }
    } else if(a == 3){
        if(b == 1) {
            return make_pair(0, 1);
        } else if(b == 2) {
            return make_pair(1, 0);
        } else if(b == 3){
            return make_pair(0, 0);
        }
    }
    return make_pair(-1, -1);
}

// 返回A, B的下一个状态
DULLI nextAB(ulli lastA, ulli lastB) {
    return make_pair(A[lastA][lastB], B[lastA][lastB]);
}

// 循环节长度
ulli cycleLen;

// dfn计时器(从1开始计时)
ulli clk;

// A的总分
ulli ansA;

// B的总分
ulli ansB;

DULLI operator += (DULLI &a, DULLI b) {
    a.first += b.first;
    a.second += b.second;
    return a;
}

// work()函数,负责计算ans
void work() {
    // 保存原始变量
    ulli initA = a, initB = b, initK = k;

    cycleLen = -1;

    // 循环节开始和结束位置,循环节的值
    DULLI cycleStart, cycleEnd;

    ulli cycleValA, cycleValB;

    // 计算循环结长度
    do {

        // 维护dfn序,维护前缀和
        dfn[a][b] = ++ clk;
        val[a][b] += get(a, b);

        // 更新答案
        k --;
        ansA += get(a, b).first;
        ansB += get(a, b).second;

        if(k == 0) {
            return;
        }

        // 下一个a, b状态
        DULLI NEXTAB = nextAB(a, b);
        ulli nextA = NEXTAB.first;
        ulli nextB = NEXTAB.second;

        // 判断是否访问过
        if(dfn[nextA][nextB]) {

            // 如果访问过说明找到了循环节

            cycleLen = dfn[a][b] - dfn[nextA][nextB] + 1;

            cycleStart = DULLI(nextA, nextB);

            cycleEnd = DULLI(a, b);

            cycleValA = val[a][b].first - val[nextA][nextB].first + get(nextA, nextB).first;

            cycleValB = val[a][b].second - val[nextA][nextB].second + get(nextA, nextB).second;

            break;

        } else {
            // 没有访问过就说明当前还在路径上

            // 维护前缀和
            val[nextA][nextB] = val[a][b];
        }

        // 下一个状态
        a = nextA;
        b = nextB;

    } while(1);

    // 消环,找循环节

    ansA += k / cycleLen * cycleValA;
    ansB += k / cycleLen * cycleValB;

    k %= cycleLen;

    a = cycleStart.first;
    b = cycleStart.second;

    // 枚举最后的一小段

    while(k --) {
        ansA += get(a, b).first;
        ansB += get(a, b).second;
        DULLI NEXTAB = nextAB(a, b);
        a = NEXTAB.first;
        b = NEXTAB.second;
    }
}

// 主函数,负责读入、调用work()、输出答案
int main() {
    cin >> k >> a >> b;
    for(int i = 1 ; i <= 3 ; i ++) {
        for(int j = 1 ; j <= 3 ; j ++) {
            cin >> A[i][j];
        }
    }
    for(int i = 1 ; i <= 3 ; i ++) {
        for(int j = 1 ; j <= 3 ; j ++) {
            cin >> B[i][j];
        }
    }
    work();
    cout << ansA << ' ' << ansB << endl;
}

  

posted @ 2017-09-23 17:21  KingSann  阅读(369)  评论(0编辑  收藏  举报