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<cnt2,x必须等于a=9×(cnt2-cnt1)÷2,B才能让前后两半相等。如果x比a大,那么M还是可以通过在前一半加9或者后一半加0的方式让最终前一半的和比后一半的和大,因为B只能在对应的另一半加9、加0,但也无济于事。同理如果x比a小,那么M可以通过在前一半加0或者后一半加9的方式让最后前一半比后一半小。

代码如下

#include<bits/stdc++.h>
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值