codeforces863C 1-2-3
C. 1-2-3time limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputIlya 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.
InputThe first line contains three numbers k, a, b (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).
OutputPrint 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.
Examplesinput10 2 1
1 1 1
1 1 1
1 1 1
2 2 2
2 2 2
2 2 2output1 9input8 1 1
2 2 1
3 3 1
3 1 3
1 1 1
2 1 1
1 2 3output5 2input5 1 1
1 2 2
2 2 2
2 2 2
1 2 2
2 2 2
2 2 2output0 0NoteIn 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; }