NC206022. 硬币游戏Ⅲ
描述
张老师和石头每年校赛都要决定谁来出最后一道题,都是通过玩游戏,每年菜哭武都能发现新的游戏。今年菜哭武选择了翻硬币游戏,谁能赢就不用出最后一道题。
有n个硬币从左到右排开,有一些是正面,有一些是反面。张老师和石头轮流选择连续最多k个(至少一个)硬币翻面,其中最右边一个硬币一定是从正面翻成反面,谁先不能行动就输掉游戏。张老师首先选择。
张老师最近忙于毕设没时间出题,也不想花时间玩游戏,想让你帮他研究一下他能否获胜。
输入描述
第一行两个正整数n, k(1≤k≤n≤106),表示总硬币个数和同时连续最多翻转的硬币个数。
第二行一个长度是n的01字符串s,第i个字符表示从左到右第i个硬币的正反面情况,1表示正面,0表示反面。
输出描述
输出一行,如果张老师能赢,则输出Yes,否则输出No。
示例1
输入:
10 2 1001001001
输出:
No
C++14(g++5.4) 解法, 执行用时: 46ms, 内存消耗: 2024K, 提交时间: 2020-05-15 10:35:34
#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; }
C++(g++ 7.5.0) 解法, 执行用时: 13ms, 内存消耗: 1400K, 提交时间: 2022-11-08 15:09:05
#include <bits/stdc++.h> using namespace std; const int N = 1000010; int n, k, m = 1; char s[N]; int getSG(int x) { return min(x & -x, m); } int main() { scanf("%d%d%s", &n, &k, s + 1); while (m * 2 < k) m <<= 1; int ans = 0; for (int i = 1; i <= n; i++) if (s[i] == '1') ans ^= getSG(i); puts(ans ? "Yes" : "No"); return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 10ms, 内存消耗: 1372K, 提交时间: 2020-07-02 20:48:45
#include<bits/stdc++.h> using namespace std; char R[1000005]; int main() { int i,j=0,n,k,m=1; scanf("%d%d%s",&n,&k,R+1); while((m<<1)<=k)m<<=1; for(i=1;i<=n;i++)if(R[i]=='1')j^=min(i&(-i),m); if(j)printf("Yes\n"); else printf("No\n"); return 0; }