codeforces1215D Ticket Game

问题链接(https://codeforces.com/problemset/problem/1215/D)

问题描述

一张票有n位数,如果这张票的前一半数字的和等于后一半数字的和(n一定是偶数),就称这张票为快乐票。有些数被擦除了,标记为’?’(’?‘的个数也是偶数),现在Monocarp 和 Bicarp 进行一个游戏,两人轮流将’?'变换成0到9的任意一个数,Monocarp先手,如果最后票为快乐票则Bicarp赢,否则Monocarp赢。

问题分析

先分别获取两部分非擦除数的和v1、v2,以及两半数中’?‘的个数cnt1、cnt2。并可以用v1、v2中大的数减小的数得到x,因问题都是对称的,所以不妨设v1>=v2,记x=v1-v2。那么问题统一为:前一半数的和为x+cnt1个’?’(值可不一,下同),后一半数的和为cnt2个’?’。
现分析以下几种情况:
若cnt1==cnt2,则M(简略表述,M代表Monocarp,B代表Bicarp)可以先对左边的’?'变9,接着无论B怎么操作,M只需要在B的操作完的那一半数的另一半数做相同的操作,就可以保证最后操作结果左边等于右边(不考虑x),也就是最后左边会比右边多一个x,所以这种情况B赢的条件是x为0,当然x为0时,B也是只需要模仿M的操作就可以使两边相等了。
若cnt1>cnt2,M在前一半不断加9,或在后一半不断加0,即使是不考虑x,B无论怎么操作也不能使两半相等。
若cnt1

代码如下

#include
using namespace std;
const int N=2e5+5;

#define endl '\n'

char str[N]; 

int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int n,cnt1,cnt2,v1,v2,v;
	cin>>n>>str;
	cnt1=cnt2=v1=v2=0;
	for(int i=0,half=n/2;i<half;i++){
		if(str[i]=='?') cnt1++;
		else v1+=str[i]-'0';
	}
	for(int i=n/2;i<n;i++){
		if(str[i]=='?') cnt2++;
		else v2+=str[i]-'0';
	}
	if(v1<v2){
		swap(v1,v2);
		swap(cnt1,cnt2);
	}
	v=v1-v2;
	if(cnt1==cnt2&&!v) cout<<"Bicarp"<<endl;
	else if(cnt2>cnt1&&v==(cnt2-cnt1)/2*9) cout<<"Bicarp"<<endl;
	else cout<<"Monocarp"<<endl;
	return 0;
}

你可能感兴趣的:(博弈,Codeforces,博弈)