Codeforces 549C 题解

tags

模拟 博弈 数学

中文题面翻译

维斯特洛有 n 座城市。第 i 座城市居住着 ai 个人。丹妮莉丝(Daenerys)和史坦尼斯(Stannis)在下一盘棋:一方选择某座城池,一举将其夷为平地。这样,所有居民都会不幸身亡。史坦尼斯先开始。当维斯特洛只剩下 k 座城市时,游戏结束。

预言中说,如果存活居民的总数是双数,那么丹妮莉丝获胜:史坦尼斯被斩首,丹妮莉丝登上铁王座。如果幸存居民总数为奇数,则史坦尼斯获胜,一切走向完全相反。

培提尔-贝里席大人想知道他应该支持哪位王位候选人,因此他想知道哪位候选人有制胜的策略。回答贝里席大人的这个问题,也许您就能成为下一任赫伦霍尔领主。

输入
第一行包含两个空格分隔的正整数 n 和 k ( 1 ≤ k ≤ n ≤ 2·105 )–维斯特洛的初始城市数和游戏结束时的城市数。

第二行包含 n 个空格分隔的正整数 ai ( 1 ≤ ai ≤ 106 ),代表维斯特洛每个城市的人口数。
输出
如果丹妮莉丝获胜,则打印字符串"丹妮莉丝"(不带引号);如果史坦尼斯获胜,则打印字符串"史坦尼斯"(不带引号)。

思路

这是一个博弈问题
简而言之,给定数组a,Daenerys的目标是让数组和为偶数,Stannis的目标是让数组和为奇数,俩人轮流操作,每次可以删除数组中一个数
由于k(k = 2,3,4,5,6,7,…)个偶数和仍为偶数,可以知道Daenerys和Stannis的争夺焦点是在奇数,因为k个奇数相加,若k=2n+1(n = 1,2,3,4,…)即k为奇数则结果为奇数,若k=2n(n = 1,2,3,4,…)即k为偶数则结果为偶数
定义奇数个数为odd
这样我们对两人的行为定义的更加明确了,Daenerys应当使得odd % 2 == 0,而Stannis应当使得odd % 2 == 1

代码

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


signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n, k; cin >> n >> k;
	int a, odd = 0, even = 0;
	int s = 0, step_s, step_d;
	// start end
	for (int i = 1; i <= n; i++) {
		cin >> a;
		if (a & 1) odd++;
		else even++;
	}
	if (n - k & 1) step_s = (n - k) / 2 + 1, step_d = (n - k) / 2;
	else step_s = step_d = (n - k) / 2;
	
	if (step_s >= even && (k & 1)) cout << "Stannis";
	else if (step_d >= even && !(k & 1)) cout << "Daenerys";
	else if (!even) {
		if (k & 1) cout << "Stannis";
		else cout << "Daenerys";
	}
	else if (!odd) cout << "Daenerys";
	else if (step_d >= odd) cout << "Daenerys";
	else {
		bool state = 1; // S
		while (n > k) {
			if (state) {
				if (odd & 1) {
					if (even) even--;
					else odd--;
				}
				else {
					if (!(step_s > step_d)) {
						cout << "Daenerys";
						return 0;
					}
					else {
						cout << "Stannis";
						return 0;
					}
				}
				step_s--;
			}
			else {
				if (!(odd & 1)) {
					if (even) even--;
					else odd--;
				}
				else odd--;
				step_d--;
			}
			n--;
			state = !state;
		}
		if (odd & 1) cout << "Stannis";
		else cout << "Daenerys";
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值