阶梯Nim
类似题目:
个位置,每个位置有个石子,两个人轮流操作,把第个位置的石子挪到个位置。谁不能在操作,谁为输。
结论:
求奇数位上的石子数的异或和
洛谷 P3480
题目大意:
n对石子,每堆石子个个数不能少于前一堆石子,两个人轮流拿石子,谁不能拿为输。
思路:
因为每堆石子的个数不能少于前一堆石子。那么如果我拿走第堆的石子,那么第堆石子可拿的个数就会变多,这里就连可以看成类似的阶梯Nim,对于每堆石子的差值,是一个倒过来的阶梯Nim
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int Mod = 1e9 + 7;
const double eps = 1e-8;
typedef pair<int, int> psi;
typedef bitset<10> B;
int c[maxn];
int main(int args, char *argc[]){
int T; cin >> T;
while(T --) {
int n; cin >> n;
int pre = 0;
for (int i = 1, x; i <= n; i ++) {
cin >> x;
c[i] = x - pre;
pre = x;
}
int ans = 0;
for (int i = n; i >= 1; i -= 2)
ans ^= c[i];
if(ans) cout << "TAK\n";
else cout << "NIE\n";
}
return 0;
}
洛谷P2575
题目大意:
两个人下棋,棋盘是一个的棋盘,棋盘上有若干棋子。对于每个棋子,只能向右移动到离他最近的空格,谁不能移动谁就输
思路:
我们可以观察一下,空格的数量的不变的,而
挪动第二个黑子的话,就变成
这样就可以看成一个阶梯Nim的模型,石子由第一个阶梯移到第二个阶梯,而每个空格就是一个阶梯的分界线
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int Mod = 1e9 + 7;
const double eps = 1e-8;
typedef pair<int, int> psi;
int a[25];
int getAns(int x) {
memset(a, 0, sizeof(a));
for (int i = 0, k; i < x; i ++) {
cin >> k;
a[k] = 1;
}
int cnt = 0, tot = 0, ans = 0;
for (int i = 20; i >= 1; i --) {
if(!a[i]) {
if(tot) {
ans ^= tot;
tot = 0;
}
cnt ^= 1;
}else
if(cnt) tot ++;
}
if(tot) ans ^= tot;
return ans;
}
int main(int argc, char *args[]) {
int T; cin >> T;
while(T --) {
int n; cin >> n;
int ans = 0;
for (int i = 1, x; i <= n; i ++) {
cin >> x;
ans ^= getAns(x);
}
if(ans) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}