【codeforces题解】 Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)

A. * Break

nm矩形方格代表*房间,最少在多少个墙壁上打洞,使得无论位于*的哪个房间都能逃走。
【codeforces题解】  Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
【codeforces题解】  Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
思路:根据例子构造解,并证明此解最优
易构造S型通路,res=m
n;
观点(1)、递归
(2)保证一条欧拉路(考虑入度和出度)
直接输出n*m即可,代码略
(3)染色法(朋友提出的,本人未试)

输出m*n,代码略

B. Restore Modulo

给定数组a,判断能否按以下方法构造:
存在n,m,c,s; n,m>0;0<=c<m;s>=0。
(1) a1 = s (mod m)
(2) a i = a i-1 +c (mod m) i=1…n;
如果存在,并找出最大的m,以及任意符合要求的c
【codeforces题解】  Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
【codeforces题解】  Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
思路:
注意到0<=c<m,于是 a i = a i-1 +c (mod m) 等价为——
根据a i - a i-1的正负性(1)a i - a i-1 = c (2) a i - a i-1 = c -m
故构造差分数组dd,并将其划分——负数一类dn,非负一类dp

分情况讨论,探索到什么时候不存在,什么m无穷大
不存在<=>dn元素不全相等,dp内元素不全相等
|| 算出的m不符合题中范围(易忽略!)
m无穷大<=>dn和dp有一个为空
剩余情形根据(1)a i - a i-1 = c (2) a i - a i-1 = c -m即算出m,c

代码如下:

#include<iostream>
#include<stdio.h>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<unordered_set>
#include<set>
#include<map>
#include<sstream>
using namespace std;

#define int long long
const int INT = 0x3f3f3f3f;

unsigned main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		vector<int>nums;
		vector<int>dp;
		vector<int>dn;
		int ma = 0;
		for (int i = 0; i < n; ++i) {
			int x;
			cin >> x;
			nums.push_back(x);
			ma = (x > ma) ? x : ma;
		}

		for (int i = 0; i < n - 1; ++i) {
			int y = nums[i+1] - nums[i];
			if (y >= 0)
				dp.push_back(y);
			else
				dn.push_back(y);
		}

		int len1 = dp.size(), len2 = dn.size();
		int flag = 1, p = -1, q = 1;
		if (len1) {
			int temp = dp[0];
			for (auto i : dp) {
				if (i != temp) {
					flag = 0;
					break;
				}
			}
			if (flag)
				p = temp;
		}
		if (len2) {
			int temp = dn[0];
			for (auto j : dn) {
				if (j != temp) {
					flag = 0;
					break;
				}
			}
			if (flag)
				q = temp;
		}
		int c = p, m = p - q;
		if (p>=0 && q<0 && m <= ma) {
			flag = 0;
		}
		if (flag == 0) {
			cout << -1 << "\n";
			continue;
		}
		if (len1 == 0 || len2 == 0) {
			cout << 0 << "\n";
			continue;
		}
		cout << m << " " << c << "\n";
	}
}

C. Basic Diplomacy

n个朋友,m天,每天找一个朋友玩,每个朋友玩的天数不能超过(m/2)上取整给出m天中每天哪些朋友有空。判断是否满足要求,是则给出方案。

【codeforces题解】  Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
【codeforces题解】  Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)
分析:
注意到对任何一种选择方法(先不考虑题目限制),最多一人(A)天数cnt(A)超过(m+1)/2。对这种方法,遍历每一天,如果这一天选了A,看看这一天可选的朋友除了A有没有其他人——如果有,则替换,–cnt(A)。m天遍历完后最后看是否符合要求。
代码如下:

#include<iostream>
#include<stdio.h>
#include<vector>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<unordered_set>
#include<set>
#include<map>
#include<sstream>
using namespace std;

#define int long long
const int INT = 0x3f3f3f3f;

unsigned main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int t;
	cin >> t;
	while (t--) {
		int n, m;
		cin >> n >> m;

		vector<int>ans;
		vector<vector<int>>arr(m);
		vector<int>cnt(n+1,0);

		for (int i = 0; i < m; ++i) {
			int k,x;
			cin >> k;
			for (int j = 0; j < k; ++j) {
				cin >> x;
				arr[i].push_back(x);
			}
			cnt[x]++;
			ans.push_back(x);
		}
		for (int i = 0; i < m; ++i) {
			if (cnt[ans[i]] > (m + 1) / 2) {
				if (arr[i].size() >= 2) {
					--cnt[ans[i]];
					ans[i] = arr[i][0];
				}
			}
		}
		int flag = 1;
		for (int i = 0; i < m; ++i) {
			if (cnt[ans[i]] > (m + 1) / 2) {
				flag = 0;
				break;
			}
		}
		if (flag) {
			cout << "YES\n";
			for (int i = 0; i < m; ++i) {
				cout << ans[i] << " ";
			}
			cout << endl;
		}
		else {
			cout << "NO\n";
		}
	}
}
上一篇:解决使用round函数后,某些值小数位没有保留对应位数


下一篇:2021-04-08