2123D-Binary String Battle

题目

艾丽斯和鲍勃得到一个长度为 \(n\) 的二进制字符串 \(s\),以及一个整数 \(k\)(满足 \(1 \le k < n\))。

如果艾丽斯能够将字符串 \(s\) 中的所有字符都变为零,则艾丽斯获胜。如果艾丽斯在有限步内无法获胜,则鲍勃获胜。

艾丽斯和鲍勃轮流操作,艾丽斯先开始。

  • 在艾丽斯的回合,她可以选择字符串 \(s\) 中任意一个长度为 \(k\)子序列,然后将该子序列中的所有字符设为零。
  • 在鲍勃的回合,他可以选择字符串 \(s\) 中任意一个长度为 \(k\)子串,然后将该子串中的所有字符设为一。

注意,如果在游戏进行中任意时候(包括艾丽斯和鲍勃回合之间),字符串全部为零,则艾丽斯获胜。

请判断在最优策略下,谁将获胜。

子序列:字符串 \(s\) 的一个字符集合,字符在 \(s\) 中按顺序出现,但不需要相邻。
子串:字符串 \(s\) 的一个连续字符区间,字符必须是相邻的。


输入格式:

  • 第一行包含一个整数 \(t\)\(1 \le t \le 10^4\)),表示测试用例的数量。
  • 每个测试用例的第一行包含两个整数 \(n\)\(k\)\(2 \le n \le 2 \times 10^5\)\(1 \le k < n\))。
  • 第二行包含长度为 \(n\) 的二进制字符串 \(s\)

保证所有测试用例中 \(n\) 的总和不超过 \(2 \times 10^5\)

思路

\(cnt\)\(1\)的个数,
一.当\(cnt <= k\)\(alice\)获胜, 否则分两种情况讨论
二.当\(n >= 2 * k\)\(bob\)获胜,因为\(alice\)操作完后,一定会有剩余,而\(bob\)可选择最左边或最右边的字串变为\(1\),且一定不会与原有的\(1\)全部重合,所以在\(bob\)操作完后,总有\(cnt>k\)
三。否则,\(n < 2 * k\)\(alice\)获胜

方法

如此类博弈,获胜问题时,优先从获胜条件,状态转移考虑,运用递推,递归的思想,进行分类讨论

code

#include <bits/stdc++.h>
using namespace std;

int t;
int n, k, cnt, l;
string s;

void solve()
{
	cin >> n >> k;
	cin >> s;
	cnt = 0;
	l = s.size();
	s = ' ' + s;
	for(int i = 1;i <= l;i++) if(s[i] == '1') cnt++;
	if(cnt <= k) {
		cout<<"alice"<<"\n";
		return;
	}
	if(n >= 2 * k){
		cout<<"bob"<<"\n";
	}else{
		cout<<"alice"<<"\n";
	}
	
}

int main(){
	ios :: sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--){
		solve();
	}
	return 0;
} 
posted @ 2025-07-27 20:01  赵梓烨  阅读(25)  评论(1)    收藏  举报