emmmm于是我咕咕咕了图论相关总结和数论相关总结。
现在暂时欠着吧....NOIP前一定补上,不会咕不会咕
于是先来水一道博弈,然而我看完题解才会.....
POJ1704
![](https://i-blog.csdnimg.cn/blog_migrate/c76b52797bb489f0387716c46010da41.jpeg)
基于女士优先的原则,格鲁吉亚总是首发。假设格鲁吉亚和鲍勃都在比赛中尽了最大努力,也就是说,如果他们中的一个知道赢得比赛的方式,他或她将能够执行。
鉴于n个西洋棋棋子的初始位置,你能预测谁将最终赢得比赛吗?
输入
输出
先将棋子按照位置升序排序,从后往前将他们两两绑定,显然若是偶数个棋子,最后刚好绑定结束,但若是奇数个,最后就会多出来一枚棋子
这枚多出来的棋子显然只可能是左边的第一颗棋子,那么我们将这颗棋子和左边缘绑定起来
从左到右观察
我们可以发现,对于第一堆,显然有意义的只有堆之间两枚被绑定的棋子的距离,同样我们能发现,第一枚棋子无论向左移动多少个位置
显然第二枚棋子总能移动相同的格子。也就是说,一对棋子与另一对棋子之间有多少个空位置堆结果是没有影响的,那么我们就只需要考虑同一对棋子之间的距离
我们把每一对棋子之间的空位视作一堆石子,在对手移动每对石子靠右的那一颗时,移动几位就相当于取几个石子,各堆的石子取尽,相当于不能再取石子
但是显然存在一些情况,因为题目规则并没有限制,所以如果我将每一对的棋子的左端棋子移动,就会导致堆中石子数增加
然而显然的是,若对手这么做要破坏棋局,我们可以将当前堆的右端棋子移动相同的步数,使堆中的棋子恢复到原来的数量,这样棋局就变的相当于没有改变
所以这种状况我们可以直接无视。
这样我们就转化成了简单的NIM问题
于是我们能够发现,根本不存在Not sure。因为NIM博弈,不存在平局!
1 #include<iostream> 2 #include<iomanip> 3 #include<cstdio> 4 #include<ctime> 5 #include<cmath> 6 #include<cstring> 7 #include<algorithm> 8 #include<cstdlib> 9 #include<stack> 10 #include<queue> 11 #include<map> 12 #include<vector> 13 using namespace std; 14 const int maxn = 2100; 15 int T; 16 int n, p[maxn]; 17 int shiki[maxn], top = 0; 18 19 inline int read() { 20 int x = 0, y = 1; 21 char ch = getchar(); 22 while(!isdigit(ch)) { 23 if(ch == '-') y = -1; 24 ch = getchar(); 25 } 26 while(isdigit(ch)) { 27 x = (x << 1) + (x << 3) + ch - '0'; 28 ch = getchar(); 29 } 30 return x * y; 31 } 32 33 int main() { 34 T = read(); 35 while(T--) { 36 memset(p, 0, sizeof(p)); 37 memset(shiki, 0, sizeof(shiki)); 38 n = read(); top = 0; 39 for(int i = 1; i <= n; ++i) p[i] = read(); 40 sort(p + 1, p + n + 1); 41 for(int i = n; i >= 1; i -= 2) { 42 if(i == 1) { 43 shiki[++top] = p[i] - 1; 44 break; 45 } 46 shiki[++top] = p[i] - p[i - 1] - 1; 47 } 48 int ans = 0; 49 for(int i = 1; i <= top; ++i) 50 ans ^= shiki[i]; 51 if(ans) printf("Georgia will win\n"); 52 else printf("Bob will win\n"); 53 } 54 return 0; 55 }