「解题报告」ARC155D Avoid Coprime Game
还不错的题,但是这场的 A, B, C 出的是真的恶心。分类讨论你马呢。
可以改写一下过程,改成选择一个数后将所有
首先有一个朴素的想法:假如当前
但是有一个问题:我们不知道之前选了多少等于
我们先不考虑大于等于
此时我们可能得到几种情况:
- 有一个人先手必胜;
- 两个人都先手必败。
如果是第一种情况,那么肯定不会选等于
而如果是第二种情况,两个人可以一直选等于
于是我们发现,我们只关心之前选的
当前有多少个等于
考虑设
枚举一步倍数是
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
int n, m, a[MAXN];
vector<int> fac[MAXN], g[MAXN];
int cnt[MAXN];
bool f[MAXN][2];
int h[MAXN];
int tmp[MAXN];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
cnt[a[i]]++;
}
m = *max_element(a + 1, a + 1 + n);
for (int i = m; i > 1; i--) {
for (int j = i; j <= m; j += i) {
fac[j].push_back(i);
tmp[i] += cnt[j] > 0;
}
}
for (int i = 2; i <= m; i++) {
for (int a : fac[i]) {
h[a] += tmp[a];
for (int b : fac[a]) if (a != b) {
h[b] -= h[a];
}
}
for (int a : fac[i]) {
if (h[a]) {
if (i != a) {
g[i].push_back(a);
}
h[a] = 0;
}
}
}
for (int i = 2; i <= m; i++) {
for (int j = i + i; j <= m; j += i) {
cnt[i] += cnt[j];
}
}
for (int i = 2; i <= m; i++) {
for (int j : g[i]) {
f[i][0] |= !f[j][1];
f[i][1] |= !f[j][0];
}
if (!f[i][0] && !f[i][1]) {
f[i][cnt[i] % 2] = 1;
}
}
for (int i = 1; i <= n; i++) {
printf(f[a[i]][0] ? "Aoki\n" : "Takahashi\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现