Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round) A&B&C

A. Prison Break

题目链接

https://codeforces.com/contest/1484/problem/A

题目大意

没读题,猜的 a*b

解题思路

同上

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

int main(){
	int t;
	cin >> t;
	while(t--){
		int a,b;
		cin >> a >> b;
		cout << a * b << "\n";
	}
	return 0;
}

B. Restore Modulo

题目链接

https://codeforces.com/contest/1484/problem/B

题目大意

由n, m, c, s四个数生成一个序列(a1,a2,a3…an),其中:

  • a1=s % m
  • ai=(ai−1+c) % m ,1 < i <= n

现在给你这样的序列a1,a2,…,an,判定是否存在可以生成这个序列的n, m, c, s。
如果存在,请使m最大。

解题思路 反证法

有题目可知,如果序列是由某个n,m,c,s生成,那就假设成立,则该序列必然满足下述条件:

  • a1=s % m
  • ai=(ai−1+c) % m ,1 < i <= n

进一步我们可以发现:
(1)当ai-1+c < m时,ai-1+c = ai
(2)当ai-1+c > m时,(ai-1+c) % m = ai
(3)序列a中的最大值maxx 必然小于 m (每一项都%m)
(4)序列a中的最大值maxx 和maxx的下一项anext 满足 (maxx + c) % m = anext,即maxx + c > m,从而 m = maxx + c - anext
【maxx已是最大值,anext只能小于maxx,即使anext不存在,根据假设,也可以由序列推导出来】

由上,我们可以扩展得到:

  • maxx < m < maxx + c
  • 当ai<ai+1时,ai + c = ai+1
  • 当ai>aI+1时,(ai + c)% m = ai+1ai+ c - ai+1 = m

很显然,当上述条件满足时,c是一个固定值,m也是一个固定值,序列元素间的差值非常关键。

进一步分析:
(1)显然,单调递增或者递减的等差序列,如1 3 5 7,c固定,但存在无数个满足条件的m。
(2)排除(1)(3)情况,如果序列元素可以由n,m,c,s生成,则序列元素间的差值存在两种情况,否则不存在n,m,c,s:
当ai<ai+1时,ai + c = ai+1,c = ai+1 - ai
当ai>aI+1时,ai+ c - ai+1 = m ,c - m = ai+1 - ai
差值1 = c > 0,差值2 = c - m < 0,两个差值中最大的即是 c
由于c - m < 0,所以 m = c + - ( c - m),且满足 maxx < m < maxx + c
(3)序列元素间的差值如果都为0,显然存在无数种情况。
代码如下

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

#define pb push_back
#define mp make_pair

const int N = 1e5 + 10;
int a[N],b[N];
set<int> s;
void sss(){
	s.clear();
	int n;
	cin >> n;
	int maxx = -1;
	for(int i = 0;i < n;i++){
		scanf("%d",&a[i]);
		maxx = max(maxx,a[i]);
	}
	for(int i = 1;i < n;i++){
		s.insert(a[i] - a[i - 1]);
	}
	if(s.size() == 0){
		cout << "0\n";
		return ;
	}
	if(s.size() == 1){
		cout << "0\n";
		return ;
	}
	if(s.size() == 2){
		int all = 0;
		int c = 0;
		for(auto it : s){
			all += abs(it);
			c = max(c,it);
		}
		if(all < maxx){
			cout << "-1\n";
			return ;
		}else{
			cout << all << " " << c << "\n";
			return ;
		}
	}else{
		cout << "-1\n";
		return ;
	}
}
 
int main(){	
	if(test)
		freopen("x.txt","r",stdin);
	int t;
	cin >> t;
	while(t--){
		sss();
	}
	return 0;
}

C. Basic Diplomacy

题目链接

https://codeforces.com/contest/1484/problem/C

题目大意

4 6
1 1
2 1 2
3 1 2 3
4 1 2 3 4
2 2 3
1 3
A计划打n = 6天游戏,需要朋友一块玩,有m = 4位朋友。
每天只有一些朋友有空。如第三天,只有1 2 3有空。
要求每位朋友一起玩的次数不超过 向上取整ceil
判定是否有解。

解题思路 贪心

将每天的人选存入一个二维vector中,然后从可选择的人数最小的vector开始,每次选取已玩耍次数最低的人,最后判定出现次数最多的人是否满足限制。

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

#define pb push_back
#define mp make_pair
const int N = 1e5 + 5;
int f[N];
vector<vector<int> > v;
vector<int> res;
bool cmp(vector<int> a,vector<int> b){
	return a.size() < b.size();
}
void sss(){
	int n,m;
	cin >> n >> m;
	int maxx = 0;
	v.clear();
	res.resize(m);
	for(int i = 0;i < N;i++) f[i] = 0;
	int p = ceil( 1.0 * m / 2.0);
	for(int i = 0;i < m;i++){
		int x,y;
		cin >> x;
		vector<int> vv;
		vv.pb(i);//记录坐标
		for(int j = 1;j <= x;j++){
			cin >> y;
			vv.pb(y);
		}
		v.pb(vv);
	}
	sort(v.begin(),v.end(),cmp);
	for(int i = 0;i < m;i++){
		int sz = v[i].size();
		int num = v[i][1];
		for(int j = 1;j < sz;j++){
			if(f[num] > f[v[i][j]]){
				num = v[i][j];
			}
		}
		f[num]++;
		res[v[i][0]] = num;//按坐标对应记录num
		maxx = max(maxx,f[num]);
	}
	if(maxx > p){
		cout << "NO\n";
		return ;
	}else{
		cout << "YES\n";
		for(auto it:res){
			cout << it << " ";
		}
		cout << "\n";
		return ;
	}
}
int main(){
	//freopen("x.txt","r",stdin);
	int t;
	cin >> t;
	while(t--){
		sss();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值