好久没写过题解了....得找回一下原来写题解总结的习惯
题目大意:
就是现在Ivica和Marica两个人在玩一个游戏
初始的时候,有一个数m = 1,现在连个人轮流对m进行改变,每次可以选择将m变为原来的2倍,或者将m加上1,并且不能使改变后的值比n大,谁将m变为n谁就输了
给定n,Ivica先手,假定两个人都足够聪明,问谁一定会获胜
其中n <= 1e15, 每次 test case 的n的个数数小于等于5, 时间限制500ms
大致思路:
首先,谁走到n处谁就输,所以n是N点(必败点), 对于N - 1,一定是P点(必胜点)。
首先有一个明显的结论是如果n是偶数,那么先手一定败,也就是说,1是N点,这个很容易解释,就是1是一个奇数,先手无论采取怎样的操作都将使得齐变成偶数,这样,后手只需要每次都将n变成奇数( + 1)即可,最终先手都会使得m变成n,先手必败。
这个也可以从下面这个方法中分析出来:
首先若n是偶数,那么不难发现[ n / 2, n]之间的数中,奇数都是P点,偶数都是N点,当n / 2是奇数时, [(n / 2 - 1) / 2, (n / 2 - 1)]之间的所有奇数数乘上2一定是[ n / 2, n]中的N点,而加上1一定是N点(偶数)所以 [(n / 2 - 1) / 2, (n / 2 - 1)]之间所有奇数数是P点,所有偶数是N点,(n / 2)是偶数时同理, 依次递推下去,当n是偶数时, 所有偶数是N点,所有奇数是P点,那么1是P点,所以n是偶数时Marica获胜。
当n是奇数时,如果(n + 1) / 2是奇数,(n - 1) / 2是偶数,则由[(n + 1) / 2, n]中所有奇数是N点,所有偶数是P点,那么(n - 1)/2乘上2到达偶数点P点,(n - 1) / 2也是N点, 同样的可以知道[(n - 1)/4 + 1, (n - 1) / 2]中的所有数都是N点,因为他们乘上二一定到达偶数点且属于[ (n + 1) / 2, n],那么[ (n - 1) /. 4 + 1, (n - 1) / 2]中的所有点是N点,而对于(n - 1) / 4, 无论加上1(变成(n - 1)/ 4 + 1)还是乘上2(变成(n - 1) / 2)都是到达N点, 那么(n - 1) / 4是P点, 这样我们可以发现一个问题:
我们可以讲所有大于n的点看成是N点, 这样对于(n + 1) / 2是奇数时可以发现, n的位置和(n - 1) / 4 + 1的位置具有一样的性质,也就是说n和(n - 1) / 4 + 1具有一样的结果。
同样的当(n + 1) / 2是偶数时,(n + 1) / 4和n有一样的性质。
这样每次向下找与n同样的性质的数(变成(n + 1) /4或是变成(n + 3) / 4)如果还是奇数就继续,如果变成了1,说明此时的n对应1是N点,Ivica获胜,如果n变成了偶数,说明1是P点,Marica获胜
代码如下:
Result : Accepted Time : 10 ms Memory : 2662 KB
/* * Author: Gatevin * Created Time: 2014/11/7 12:30:54 * File Name: hehe.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; lint n; int t; int main() { scanf("%d", &t); while(t--) { //cin>>n; scanf("%lld", &n); if(n & 1) { while(n > 2 && (n & 1)) { if(((n + 1)/2) & 1) n = (n + 3) / 4; else n = (n + 1) / 4; } if(n == 1) { printf("Ivica\n"); continue; } printf("Marica\n"); } else { printf("Marica\n"); continue; } } return 0; }