我们翻硬币的时候,可以理解成把最后一个硬币替换成最多前面k-1,最少0个硬币。因为如果在一个位置有两个同样的硬币,他们的sg函数相同,互相抵消。这样我们就转化为k堆独立的硬币问题。
令2^p≤k<2^(p+1),第i个硬币的sg函数是min(lowbit(i),2^p )。
可以归纳法证明。如果i-1之前的sg函数满足条件,那么对于i的情况,如果i是奇数,前一个sg函数一定是2^p,其中p不小于1。注意到每一个sg函数都是一个bit,如果要xor掉p位的bit,至少要经过一个p+1位,此时的xor值不会达到1。因此,任何时刻sg函数都不会达到1。如果i是2的倍数,假设i=(2m+1)2^p,那么在到达上一个2^p倍数之前一定能遍历到所有的小于2^p的值,如果k≥2^p的情况下一定都能取到,因此sg函数至少应该是2^p。同时,当到达2^(p+1)的情况时又复现了之前提到的i是奇数的情况,要抵消掉这个值一定要达到更高的幂次,因此最大达到2^p。当k比较小的时候,我们只需要考虑对应二进制位的前缀和就可以得出sg函数的上界,而且一定能达到。
整体复杂度是线性的。
#include<bits/stdc++.h> using namespace std; typedef long long ll; char str[1001000]; int n; int k; int maxsg; int sg(int i){ int ans = i & (-i); return min(ans,maxsg); } int main() { cin>>n>>k; cin>>str; maxsg=1; while(k>1){ k/=2; maxsg*=2; } int sgsum = 0; for(int i=0;i<n;i++){ if(str[i]=='1') sgsum ^= sg(i+1); } if(sgsum)cout<<"Yes"<<endl; else cout<<"No"<<endl; return 0; }