【Codeforces Round #721 (Div. 2) 】Codeforces-1527

本文探讨了两种游戏策略问题,包括基于二进制递减的获胜策略和回文串游戏的必败态分析。对于非回文串转化为回文串的问题,提出了最优解法。同时,介绍了序列配对权重的计算方法,展示了如何根据序列动态更新权重总和。涉及算法设计和逻辑推理。
摘要由CSDN通过智能技术生成

掉大分+自闭场QAQ

A. And Then There Were K

随便瞎搞一个数 10111000 1 ( 2 ) 101110001_{(2)} 101110001(2),然后递减对齐观察。
1011    1    000 [ 1 ] ( 2 ) 1011\;1\;000[1]_{(2)} 10111000[1](2)
1011 [ 1 ] 000 [ 0 ] ( 2 ) 1011[1]000[0]_{(2)} 1011[1]000[0](2)
1011 [ 0 ] 111    1 ( 2 ) 1011[0]111\;1_{(2)} 1011[0]1111(2)

[ 1 ] 0000000 0 ( 2 ) [1]00000000_{(2)} [1]00000000(2)
[ 0 ] 1111111 1 ( 2 ) [0]11111111_{(2)} [0]11111111(2)
显然找到最高位的1后再-1后的&结果为0。一开始暴力求解t了一次,我菜死了呜呜

void solves(){
	int n;cin>>n;
	int ans=1;
	while(ans<=n) ans*=2;
	ans/=2;
	cout<<ans-1<<endl;
}

B1. Palindrome Game (easy version)

思维受限了,一个多小时里对自己的假思路深信不疑。。我好傻QAQ
详细阐述一下必败态。
我们记0的个数为cnt,
1.cnt=1时BOB win
2.cnt为奇数(cnt!=1)时,只要ALICE先选取中间的0(第一步选取非中间的0是必败态),无论BOB选取哪个,ALICE都能选取和它对称的那个0。一直到剩下最后的一对0,此时ALICE反转操作即可。
举个栗子:00000
A 00100
B 01100
A 01110
B 11110
A reverse
B 11111
3.cnt为偶数时,BOB可以不停选取和ALICE所选取的对称的0,一直到剩下最后一对0,此时BOB进行反转操作即可。举个栗子:000000
A 100000
B 100001
A 110001
B 110011
A 111011
B reverse
A 111111

其实讲了这么多,我只是想表达这个sb题的必败态就是先选取有对称0的那个。。cnt=1的时候没有对称0,后手胜。cnt为奇数时,先手选取中点,后手不得不选取先对称0,导致先手必胜。cnt为偶数时,先手不得不先选取对称0,导致后手必胜。

void solves(){
	int n;cin>>n>>s;
	int cnt=0;
	for(auto x:s){
		if(x=='0') cnt++;
	}
	if(cnt&1){
		if(cnt==1)cout<<"BOB\n";
		else cout<<"ALICE\n";
	} else{
		cout<<"BOB\n";
	}
}

B2. Palindrome Game (hard version)

这里我们只对一开始为非回文串进行讨论。
先给出结论。记 将非回文串变为回文串的最少改变的0的个数为cnt,记通过最少改变次数后的回文串的0的个数为o。当cnt=1且o=1时,ALICE和BOB是平手,其他情况都是ALICE胜利。
结论有比较详细的讨论证明,但是有点太长了,我不想写了(真的太长不想写,有兴趣的话可以私信一起交流)。这里就简单提一下分析的思路QAQ
我们记ALICE的花费为A,BOB的花费为B。在easy version分析必败态的时候我们知道,当最初的string是回文时(ALICE先手),两人都使用最优策略的情况下,当0的个数为1时,有【A=1,B=0】;当0的个数是偶数时,有【B+2=A】;0的个数为奇数是,有【A+1=B】。
显然,我们发现当一开始都为回文串的时候,两人在使用最优策略的情况下,二者花费的差值不超过2。那么我们可以对cnt=1,cnt=2,cnt>2来进行讨论。
当cnt=1时,有…(自己讨论一下先后手。只有当o=1时是DRAW,其他情况都是ALICE win)
cnt=2,有…(自己讨论一下先后手,反正讨论完的结果都是ALICE win)
cnt>2时,显然都是ALICE win。

void solves(){
	int n;cin>>n>>s;
	int cnt=0;
	int o=count(s.begin(),s.end(),'0');
	for(int l=0,r=n-1;l<r;++l,--r){
		if(s[l]!=s[r]) cnt++;
	}
	o-=cnt;
	if(!cnt){
		if(o&1){
			if(o==1)cout<<"BOB\n";
			else cout<<"ALICE\n";
		} else{
			cout<<"BOB\n";
		}
	} else{
		if(!o){
			cout<<"ALICE\n";return ;
		}
		if(cnt==1){
			if(o==1) cout<<"DRAW\n";
			else cout<<"ALICE\n";
		} else{
			cout<<"ALICE\n";
		}
	}
}

C. Sequence Pair Weight

想想每对pair都会在哪些区间上

void solves(){
	int n;cin>>n;
	ll ans=0;
	map<ll,ll>mp;
	for(int i=0;i<n;++i){
		int x;cin>>x;
		ans+=mp[x]*(n-i);
		mp[x]+=(i+1);
	}
	cout<<ans<<endl;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值