题目描述:
Input:
Output:
Samples:
本蒟蒻人生第一道不看题解做出的思维题
思路分析:
根据题目所说,问号及字符串总长度都是偶数,那么我们就可以将这个字符串按照题目要求分为两部分来看待,我们在输入结束后就可以先统计一下不算问号时左右两边数的总和,我们可以想象一下如果我们是Monocarp,我们的最终目的是让左右两边不等,我们就一定会选择总和较大的一边给它加上9,而Bicarp要想让两边之和相等,只能尽可能减小差距,只能在另一边也加上9,这样他们的操作就被抵消掉了。此时我们可以特判一下,如果左右两边的总和相等且等号数量相等(包括都是0个),那么我们直接让Bicarp赢就行啦,因为Monocarp先手,每次他操作完之后造成的左右差值后手的Bicarp都可以在下一次操作中追回来。另外,如果两边的问号数量不相等,且等号多的那一边数字总和还大,那Bicarp无论如何也赢不了啦,因为他们所填的值不能是负数,他们的任何操作只会让两边差值不变甚至更大。最后,我们就要考虑一边问号多,另一边总和大的情况了。
我们可以先想象一下,如果总和大的一边和另一边的差值比两边问号的差值的一半的九倍还要大,那么Bicarp必输,因为此时Monocarp一定不会去帮Bicarp追回差距。那么如果小于两边问号的差值的一半的九倍那?Monocarp可以全部填9让问号多的一边的值比另一边还大,那么此时Bicarp一定是无力回天的,又输了,根据本段所述,两边初始差值只有恰好等于两边问号的差值的一半的九倍时,Bicarp才能胜利。
综上我们判断输赢方式有三种情况:
1. 两边问号数量相等看两边值相不相等。
2. 等号多和初始总和大是否集合于一边。
3. 两边差值是否等于两边问号的差值的一半的九倍。
然后这个问题就解决了。
上代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 const int N=1e6+10; 6 int a[N],left,right; 7 int sum_l,sum_r; 8 int main(){ 9 int n; 10 scanf("%d ",&n); 11 for(int i=1;i<=n;++i){ 12 char ch=getchar(); 13 if(ch=='?'){ //统计两边等号数及初始总和 14 if(i<=n/2) sum_l++; 15 else sum_r++; 16 } 17 else{ 18 int num=ch-'0'; 19 if(i<=n/2) left+=num; 20 else right+=num; 21 } 22 } 23 if(sum_r==sum_l){ //两边初始等号数量相等的情况 24 if(left==right){ 25 printf("Bicarp "); 26 return 0; 27 } 28 else{ 29 printf("Monocarp "); 30 return 0; 31 } 32 } 33 if((left>right&&sum_l>sum_r)||(left<right&&sum_l<sum_r)){ //等号多和初始总和大集中一边情况 34 printf("Monocarp "); 35 return 0; 36 } 37 int chazhi=abs(left-right); 38 int cases=abs(sum_l-sum_r); 39 if(chazhi==cases/2*9){ //情况3 40 printf("Bicarp "); 41 return 0; 42 } 43 printf("Monocarp "); //以上都不满足,Momocarp胜 44 return 0; 45 }