取石子(九)(十)(nyoj 888 && 913)
2014-05-28 21:48
281 查看
nyoj 888:点击打开链接
反nim 详细看这里:点击打开链接
nyoj 913:点击打开链接
算是找规律的题吧……讲所有的sg值异或起来,结果为0先手输,否则后手输。
其中第二堆和第四堆要将所有的sg值算出来,其余堆都可以找到规律。
第一堆的sg值:
打表结果 规律很好找:
第三堆就是尼姆。
第五堆sg值:
结果:
第六堆及第六堆以上的,就是巴什博弈,sg值就是模(k + 1)以后的值。
第二堆和第四堆直接看最后的程序:
反nim 详细看这里:点击打开链接
#include <stdio.h> int main (void) { int n, t; scanf("%d", &t); while(t --) { scanf("%d", &n); int a, count = 0, sum = 0; int i; for(i = 0; i < n; i++) { scanf("%d", &a); sum ^= a; if(a > 1) count++; } if(count == 1)//充裕堆等于1必胜 printf("Yougth\n"); else if(count >= 2 && sum != 0)//充裕堆大于2且异或和不为0必胜 printf("Yougth\n"); else if(count == 0 && sum == 0)//充裕堆为0且是偶数堆必胜 printf("Yougth\n"); else printf("Hrdv\n"); } return 0; }
nyoj 913:点击打开链接
算是找规律的题吧……讲所有的sg值异或起来,结果为0先手输,否则后手输。
其中第二堆和第四堆要将所有的sg值算出来,其余堆都可以找到规律。
第一堆的sg值:
#include <stdio.h> #include <string.h> int sg[100]; int getsg(int n) { if(sg != -1) return sg ; int i; bool vis[100]; memset(vis, 0, sizeof(vis)); for(i = 1; i <= n; i *= 2) if(n >= i) vis[getsg(n - i)] = 1; for(i = 0; i < 100; i++) if(!vis[i]) break; return sg = i; } int main (void) { int i; memset(sg, -1, sizeof(sg)); sg[0] = 0; for(i = 1; i < 100; i++) int ok = getsg(i); for(i = 0; i < 100; i++) printf("%d ", sg[i]); return 0; }
打表结果 规律很好找:
0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
第三堆就是尼姆。
第五堆sg值:
#include <stdio.h> #include <string.h> int sg[1010]; int getsg(int n) { if(sg != -1) return sg ; int i; bool vis[1000]; memset(vis, 0, sizeof(vis)); for(i = 1; i <= 1010; i += 2) { if(n >= i) vis[getsg(n - i)] = 1; else break; } for(i = 0; i < 1000; i++) if(!vis[i]) break; return sg = i; } int main (void) { int i; memset(sg, -1, sizeof(sg)); sg[0] = 0; for(i = 1; i < 1010; i++) int ok = getsg(i); for(i = 0; i < 1010; i++) printf("%d ", sg[i]); return 0; }
结果:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
第六堆及第六堆以上的,就是巴什博弈,sg值就是模(k + 1)以后的值。
第二堆和第四堆直接看最后的程序:
#include <stdio.h> #include <string.h> int a[20];//斐波那次数列 int sg[1010], sg2[1010];//sg-第四堆 sg2-第二堆 int getsg2(int n) {//求sg2 if(sg2 != -1) return sg2 ; int i; bool vis[100]; memset(vis, 0, sizeof(vis)); for(i = 0; i < 20; i++) if(n >= a[i]) vis[getsg2(n - a[i])] = 1; for(i = 0; i < 100; i++) if(vis[i] == 0) break; return sg2 = i; } int getsg4(int n) {//求sg if(sg != -1) return sg ; int i; bool vis[1000]; memset(vis, 0, sizeof(vis)); vis[getsg4(n - 1)] = 1; for(i = 2; i <= 1010; i += 2) { if(n >= i) vis[getsg4(n - i)] = 1; else break; } for(i = 0; i < 1000; i++) if(!vis[i]) break; return sg = i; } int main (void) { int n, i; //求第二堆和第四堆的sg值 memset(sg, -1, sizeof(sg)); memset(sg2, -1, sizeof(sg)); sg[0] = 0; sg2[0] = 0; for(i = 1; i < 1010; i++) int ok = getsg4(i); a[0] = 1; a[1] = 2; for(i = 2; i < 20 ; i++) a[i] = a[i - 1] + a[i - 2]; for(i = 1; i < 1010; i++) int ok = getsg2(i); while(scanf("%d", &n) != EOF) { if(n == 0) break; int sum = 0, a; for(i = 1; i <= n; i++) { scanf("%d", &a); if(i == 1) sum ^= (a % 3); else if(i == 2) sum ^= sg2[a]; else if(i == 3) sum ^= a; else if(i == 4) sum ^= sg[a]; else if(i == 5) sum ^= a % 2 == 0 ? 0 : 1; else sum ^= (a % (i + 1)); } if(sum == 0) printf("Hrdv\n"); else printf("Yougth\n"); } return 0; }
相关文章推荐
- NYOJ 888 取石子(九)
- NYOJ 913 取石子(十)(sg函数)
- NYOJ 题目888取石子(九)(anti-nim)
- nyoj 取石子(二) 135 (博弈&&思想)
- NYOJ 888 取石子(九)
- nyoj888 取石子(九) 反Nimm博弈
- nyoj913 取石子(十) SG函数 + Nimm博弈
- nyoj 913 取石子(十) (sg函数)
- 取石子 (四)_nyoj_161(博弈-奇异矩阵).java
- (NYOJ 43 24point)&&(HDU 1427 速算24点)
- HDU 2199 Can you solve this equation? && NYOJ 503 解方程
- nyoj 737 合并石子一(dp)
- "取石子"游戏
- NYOJ 586 疯牛 & POJ 2456(二分搜索 + 贪心)
- NYOJ-题目221 Tree
- nyoj 737 石子合并(一)(区间DP)
- 取石子(一)(nyoj-23)
- NYOJ 2065 红色病毒问题 (指数型母函数&快速幂)
- nyoj 61 传纸条(一) (双线动归)&nyoj 探寻宝藏
- Hdu 1998&&Nyoj 734 奇数阶魔方