思路
第一次操作,无论从哪个珠子开始染色,都会得到相同的长度为n - m的链,然后就是在这条链中取一段长度为m的珠子染色,当这一段珠子在链条中间的时候,就会把链条分成两段,就是一个简单的两段连续珠子的长度的sg值异或一下,求出sg[n - m]的值之后,因为aekdycoin操作了一次才从长度为n的环得到现在的状态,所以先手操作的sg值为!sg[n - m]。同时还得特判m大于n的情况,m > n时,第一次操作都不能进行,先手必败。
代码
int n, m, vis[N], sg[N], test;
void SG() {
memset(sg, 0, sizeof sg);
memset(vis, 0, sizeof vis);
for (int i = m; i <= n; i++) {
for (int j = 0; j + m <= i; j++) {
// 枚举从第j个珠子开始涂色
vis[sg[j] ^ sg[i - j - m]] = i;
}
while (vis[sg[i]] == i) {
sg[i]++;
}
}
}
void solve() {
test++;
n = read(), m = read();
SG();
cout << "Case #" << test << ": ";
if (n >= m && sg[n - m] == 0) {
// 因为无论从哪个珠子开始染色得到的都是长度为n - m的链,然后就是简单的分堆
cout << "aekdycoin" << endl;
} else {
cout << "abcdxyzk" << endl;
}
}
int main() {
int t = read();
while (t--)
solve();
return 0;
}
标签:HDU,Chain,sg,Paint,珠子,长度,3980
From: https://www.cnblogs.com/againss/p/18362572