P10506 魔法珠 题解

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; 
}
posted @ 2025-02-07 10:00  Hirasawayuiii  阅读(27)  评论(0)    收藏  举报