题目 | Agnej
“范式杯”2023牛客暑期多校训练营10
D - Agnej
https://ac.nowcoder.com/acm/contest/57364/D
题意
有个
题解
显然每一层独立,因此每一层都是一个有向图游戏,那么根据 SG 定理,对每一个层求出 SG 值再异或到一起,如果答案
为偶数
为方便,记左侧有
要求
每经过一次传递 SG 值会
为奇数
奇数情况的唯一特殊点就是最中心的一块。
为方便,中心有
- 当
时,退化为偶数情况,答案 . 当
时,需要分类讨论:有一侧为空
时,考虑边界情况 : ,每经过一次传递 SG 值会 切换,那么 .
有一侧仅一块
时,考虑边界情况 :- 抽中间一块,转移为情况
,SG 值 . - 抽
的一侧,转移为情况 ,SG 值 .
- 情况
和 的 SG 值一定包含 和 ,则 ,那么每经过一次传递 SG 值会 切换,那么 .
- 抽中间一块,转移为情况
一般情况
时,考虑边界情况 :- 抽中间一块,转移为情况
, SG 值 . - 抽左侧一块,转移为情况
,SG 值为 - 抽右侧一块,由于
,考虑边界情况 , ,
- 经过归纳得到,
.
- 抽中间一块,转移为情况
代码
#include <bits/stdc++.h>
#define endl '\n'
// #define int long long
using namespace std;
int sg(string &s)
{
int len = s.size();
int mid = len / 2;
int cnt_l = 0, cnt_r = 0;
for (int i = 0; i <= mid - 1; i++)
if (s[i] == '1')
cnt_l++;
for (int i = mid; i < len; i++)
if (s[i] == '1')
cnt_r++;
if (len % 2)
{
cnt_r -= s[mid] - '0';
if (s[mid] == '0')
return (cnt_l + cnt_r) % 2;
if (cnt_l == 0 || cnt_r == 0)
return max(cnt_l, cnt_r) % 2;
if (cnt_l == 1 || cnt_r == 1)
return 2 + (max(cnt_l, cnt_r) + 1) % 2;
return (cnt_l + cnt_r + 1) % 2;
}
return (cnt_l + cnt_r) % 2;
}
void solve()
{
int n, m;
cin >> n >> m;
int ans = 0;
while (n--)
{
string s;
cin >> s;
ans ^= sg(s);
}
if (ans)
cout << "Alice" << endl;
else
cout << "Bob" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi