codeforces 814补题

本文探讨了三道编程竞赛题目,涉及棋盘游戏、数学马戏团和格斗比赛的策略。针对每种问题,详细分析了获胜条件与解题思路,并给出了相应的C++代码实现。通过对移动规则的奇偶性分析,得出游戏胜利的条件;在数学问题中,通过分类讨论k的取值,找出满足条件的组合;在格斗比赛中,模拟战斗过程确定最少的轮数。文章适合初级编程竞赛爱好者阅读,提升算法思维。
摘要由CSDN通过智能技术生成

目录

A. Chip Game

B. Mathematical Circus

C. Fighting Tournament


A. Chip Game

题意:两个人在一个n * m 的网格的左下角进行操作,只可以进行两种操作:向上走或者向右走并且每次移动只可以移动奇数个格子,其中Burenka先走,然后是Tonya走,判断谁可以移动到队首无法移动的位置,谁胜

思路:根据规则可以找到最后一个人操作之后的格子是到网格中右上角的格子,由于限制了移动规则,所以两人最后走过的路程总和为 (n - 1 + m - 1)个格子,每个人都是使用最优的移动策略,可以很明显的看出他们的胜利和(n + m + 2)的奇偶性有关(虽然很容易通过样例看出来,但是还是需要证明一下的)

当n和m都是偶数时: 所以(n + m - 2)是偶数,对于两条边分别是奇数,由于移动的距离必须是奇数,对于向右移动时,一定是先手(Burenka)先到达【1, m】,之后的向上操作先手(Burenka)变成了后手,后手(Tonya)变成了先手移动,之后的总距离是奇数,所以一定是先手(Tonya)到达,同理四种情况可以被(n + m - 2)分成两种

1、(n + m - 2)奇数 ——Burenka胜

2、  (n + m - 2)  偶数 ——Tonya胜

代码:

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

typedef long long ll;

int main() {
	int t;
	cin >> t;
	int a, b;
	while (t -- ) {
		cin >> a >> b;
		ll ans = a + b;
		if(ans & 1) {
			printf("Burenka\n");
		}
		else {
			printf("Tonya\n");
		}
	}
	
	
	
	return 0;
}

B. Mathematical Circus

题意:给定n 和 k, 从1 - n的数中(n确保是偶数)分别拿出两个数a 和 b,使得其满足(a + k)* b可以被4整除(取余于4余数是0)

思路:

在1 - n数中进行那,证明数可以重复使用

根据k % 4进行分类

1、当k == 0时,式子为 a*b 使得其可以被4整除,可以看出,无法实现,1 - n中偶数占一半,4的倍数又是偶数的一半(带不动所以的奇数),无法使得所有数组合成a * b均满足被4整除

2、当k == 2时,1——n可以分为每四个数中会产生一个4的倍数假设这个数是i,那么可以将i-2通过加 k 使其成为4的倍数,他就可以和 i - 3组合,成为一组正确的组合

3、当k == 1是,由于每4个数可以产生一个4的倍数(从一依次算起), k = 1是,起就可以使得i-1变成4的倍数,从而可以和 i - 2 或者1 - 3进行组合,与 i 组合的数让 i 当做b,既可以满足

4、当k == 3的时候,思路与上面相同

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

void solve() {
	int n, k;
	scanf("%d%d", &n, &k);
	
	if(k % 4 == 0) printf("NO\n");
	else if(k % 2 == 1) {
		printf("YES\n");
		
		for (int i = 0; i + 4 <= n; i += 4) {
			printf("%d %d\n", i + 1, i + 2);
			printf("%d %d\n", i + 3, i + 4);
		}
		if(n % 4 == 2) {
			printf("%d %d\n", n - 1, n);
		}
	}
	else if(k % 4 == 2) {
		printf("YES\n");
		for (int i = 0; i + 4 <= n; i += 4) {
			printf("%d %d\n", i + 1, i + 4);
			printf("%d %d\n", i + 2, i + 3);
		}
		if(n % 4 == 2) {
			printf("%d %d\n", n, n - 1);
		}
	}
}

int main() {
	int t;
	scanf("%d", &t);
	
	while (t -- ) {
		solve();
	}
	
	
	
	
	return 0;
} 

C. Fighting Tournament

题意:一个数组,第 i 个数表示第 i 个人的战斗,战斗方式是依次战斗,数组中的前两个进行战斗,获胜的留在前面,失败的人回到队尾

思路:可以看出数组数组中存在一个数(max最大值)在一定的轮数后是一直赢得,想用达到这个轮数后,其他人之后就再也不回赢,最坏的情况是最大值起初位于队尾,所以最多进行n - 1轮之后进入“独孤求败”阶段,所以通过n - 1次模拟处理出,(题目中规定了,每个人的战斗力都不一样)

代码(注释上了解释) :

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

const int N = 2e5 + 5;
int a[N];
int n, q;
int c[N], b[N], d[N];
//c[]记录每个人赢了多少次
//b[]记录每个人第一次什么时候赢得
//d[]记录轮是谁赢了

void solve() {
	cin >> n >> q;
	
	for (int i = 1; i <= n; i ++ ) {
		scanf("%d", &a[i]);
		b[i] = c[i] = 0;
	}
	
	int temp = a[1];
	for (int i = 2; i <= n; i ++ ) {
		if(temp < a[i]) temp = a[i];//找到每次比试获胜的那个人 
		
		c[temp] ++ ;//记录每个人赢了多少次 
		if(b[temp] == 0) b[temp] = i - 1;//记录这个人第一次的轮次 
		d[i - 1] = temp;//记录这一轮是谁赢了 
	}
	
	while (q -- ) {
		int x, k;
		scanf("%d%d", &x, &k);
		x = a[x];
		int ans = 0;
		if(k <= n - 1) {
			//只有两者中最大可以留下,所以当走过这一轮之后,d[k]的数一定大于等于x 
			if(d[k] < x) {
				ans = 0;
			} 
			else if(d[k] == x) {
				//正好访问的真是这一轮时,所以从一开始赢也就是b[x]
				//记录的位置,到现在的位置一直都是这个人赢得 
				ans = k - b[x] + 1;
			}
			else {
				//这个人已经不可能在赢了,直接输出统计数即可 
				ans = c[x];
			}
		} 
		else {
			//最多走一轮就可以让最大值到第一位,之后只有是最大值可以赢 
			ans = c[x] + (x == n ? k - n + 1: 0);
		}
		printf("%d\n", ans);
	}
}


int main() {
	int t;
	cin >> t;
	while (t -- ) {
		solve();
	}
	
	
	
	
	return 0;
}

 由于我比较菜,目前只具备div2前3题或者前2题的水平,慢慢进步吧!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces的动态规划题单中,有基础DP、优化递推式、进阶DP、数据结构、优先队列、并查集、图论、最短路、最小生成树、数论、二分搜索等不同类型的题目。 代码中的内容是一个动态规划的例子,它采用了一个二维数组来存储中间结果,并通过递推的方式计算最优解。这个例子中,它使用了一个for循环嵌套来遍历数组,并利用状态转移方程更新数组中的值。最后输出的是计算得到的最优解。 要注意的是,这段代码是一个完整的程序,需要依赖于一些特定的输入数据才能正确运行。如果你想在Codeforces上找到更多的动态规划题目,可以访问它们的官方网站并浏览题库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [牛客练习_21314:codeforces (动态规划+01背包)](https://blog.csdn.net/qq_45750296/article/details/109587967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [leetcode双人赛-acm-challenge-workbook:acm-挑战-工作簿](https://download.csdn.net/download/weixin_38701340/19923844)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round #750 (Div. 2)E题(动态规划)](https://blog.csdn.net/m0_51506743/article/details/121083708)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值