P10506 魔法珠 题解
题目链接
题目大意
\(n\) 堆物品,分别有 \(a_1,a_2,...,a_n\) 个。两人轮流选择一堆数量大于 \(1\) 的物品,将其分解为他的所有因数,再选择这些因数中的一堆删除。当有人无法操作(物品数量皆为 \(1\))时另一人胜利。
解题思路
显然本题是博弈论问题。因为本题是将一个物品(设数量为 \(x\))分解成因数后再删除一个因数,所以先求出 \(x\) 的子情况和再异或每个因数(通过异或性质,再次异或抵消),即可模拟出删掉一个因数的情况。最后将每个子问题异或后即可得到答案
代码
// Problem: P10506 魔法珠
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P10506
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// Date: 2025-02-07 08:23:01
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(x, y) memset(x, y, sizeof(x))
#define pii pair<int, int>
#define fi first
#define se second
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)int read(){int x = 0, f = 1;char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9'){x = 10*x+c-'0';c = getchar();}return f*x;}
void writ(int x){if(x < 0){putchar('-');x = -x;}if(x > 9) writ(x/10);putchar(x%10 | 0x30);return;}
void write(int x){writ(x);puts("");}
void wr(int x){writ(x);putchar(' ');}
const int N = 105, M = 1005, inf = 0x3f3f3f3f;int n, a[N], maxn = 1000, sg[M], mk[M], ans;void getsg(){for(int i = 1;i <= maxn;i++){mst(mk, 0);int sum = 0;for(int j = 1;j*j <= i;j++){if(i%j) continue;if(j < i) sum ^= sg[j];if(i/j < i && j != i/j) sum ^= sg[i/j];}for(int j = 1;j*j <= i;j++){if(i%j) continue;if(j < i) mk[sum^sg[j]] = 1;if(i/j < i && j != i/j) mk[sum^sg[i/j]] = 1;}for(int j = 0;j <= maxn;j++){if(!mk[j]){sg[i] = j;break;}}}
}
void solve(){getsg(); // 预处理sg函数while(scanf("%d", &n) != EOF){ans = 0;for(int i = 1;i <= n;i++){int x = read();ans ^= sg[x];}if(ans) puts("freda");else puts("rainbow");}
}signed main(){solve();return 0;
}