题目大意:(取石子游戏)有n个箱子,体积为Si,当前箱子里的石子数为Ci。两个人轮流往箱子里放石子,而且每一次放是数量都有限制,不能超过当前箱子内石子数的平方。例如箱子里有3颗石子,那么下一个人就可以放1~9颗石子,直到箱子被装满。当有一方放不下石子时游戏结束,最后放不下石子的人输。
首先空间为20的时候,
ci == 20 sg = 0;
ci == 19 sg = 1;
ci == 18 sg = 2;
ci == 17 sg = 3;
…………………
直到 ci = 4 的时候 sg = 16; 显然此时可以放4 * 4 + 4 == 16个还是赢,
所以
在 4 ~ 20 范围内 sg(ci,si) = si – ci;
但是当 ci == 3 的时候 sg == 0,之后又是一个循环,所以求sg是个递归的过程;
对于任意一个si,都要找到一个临界点,这个临界点 t 显然得满足 t*t == si – t ; t–;
在临界点右边
sg(ci,si) = si – ci;
临界点左边
sg(ci,t);
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int sg( int c, int s){
int t = sqrt(s);
while(t*t + t >= s) t--;
if(c > t) return s - c;
else return sg(c, t);
}
int main(){
for (int kase(1),n;scanf("%d",&n) && n && printf("Case %d:\n",kase++);){
int si,ci,ans(0);
while(n--){
scanf("%d%d",&si,&ci);
ans ^= sg(ci,si);
}
printf( ans ? "Yes\n" : "No\n");
}
return 0;
}