Codeforces Round #829 (Div. 2)

A. Technical Support

        题目大意:

                每次一个问题Q,和一个回答A。要求每个问题Q后面都有A与之对应,问给出的字符串是不是满足这个条件

        分析:

                模拟就行了

#include <bits/stdc++.h>

using namespace std ; 
const int N = 108 ; 

void solve(){
	int n ; 
	cin >> n ; 
	string s ; 
	cin >> s ; 
	int cnt = 0 ; 
	for(int i = 0 ; i < n ; i ++){
		if(s[i] == 'Q') cnt ++ ; 
		else {
			if(cnt) cnt -- ; 
		}
	}
	if(cnt) cout << "No" << '\n' ; 
	else cout << "Yes" << '\n' ; 
}

int main(){	
	std::ios::sync_with_stdio(false) ; 
	std::cin.tie(0) ; 

	int T ; 
	cin >> T ; 
	while(T --){
		solve() ; 
	}

	return 0;
}

 B. Kevin and Permutation

        题目大意:

                有一个只包含元素1~n的序列,要求你构造出来的序列使得|min(p_{i+1}-p_{i})|的值最大

        分析:

                我们可以观察大,最大值就是\frac{n}{2},构造方法为n , n/2 , n - 1 , n/2 - 1 ...这样一直构造下去,如果长度是奇数,就将n放在序列的最后

#include <bits/stdc++.h>

using namespace std ; 
const int N = 108 ; 

void solve(){
	int n ; 
	cin >> n ; 
	if(n % 2 == 1){
		for(int i =  n / 2 , j = n - 1 ; i >= 1 ; i -- , j --){
			cout << i << ' ' << j << ' ' ; 
		}
		cout << n << '\n' ; 
	}else{
		for(int i =  n / 2 , j = n; i >= 1 ; i -- , j --){
			cout << i << ' ' << j << " \n"[i == 1] ; 
		}
	}
}

int main(){	
	std::ios::sync_with_stdio(false) ; 
	std::cin.tie(0) ; 

	int T ; 
	cin >> T ; 
	while(T --){
		solve() ; 
	}

	return 0;
}

C1. Make Nonzero Sum (easy version)
        题目大意:

                给定一个数组,你可以将数组进行不同的分组,并且每一组区间[l,r]的价值为:s_{i}=a[l]-a[l+1]+a[l +2]-a[l+3]+a[l+4]....,要求你给出一个合法的分组满足所有分组的价值之和为0

        分析:

                我们首先注意到一个性质:如果当前每个区间的长度都为一,也就是每个数自己和自己是一组,那么如果找到一个数是1,并且把它跟前面的一个数并成一组,那么1就变成了-1,那么对所有价值的和的贡献就是-2。同理,如果当前的数是-1,把它与前面一个数合并成一组,那么-1就变成了+1,对所有价值的和的贡献是+2。也就是说我们每次合并一个分组本质上就是对价值的+2或者-2操作。所以我们的策略是,首先我们将所有数单独分成一个组,如果价值是奇数,那么就一定不行输出-1;如果是偶数,那么会有总价值>0总价值<0和总价值==0之分:

        1.如果总价值大于0,我们就在序列里面找到1的位置并且把它和前面一个数合并,直到总价值为0

        2.如果总价值==0,直接输出每一个单个区间即可

        3.如果总价值<0,我们就在序列里面找-1的位置并且把它和前面一个数合并,直到总价值为0

#include <bits/stdc++.h>

using namespace std ; 
const int N = 200008 ; 
int a[N] ; 
struct node{
	int l , r ; 
}no[N] ; 
void solve(){
	int n ; 
	cin >> n ; 
	int tot = 0 ; 

	for(int i = 1 ; i <= n ; i ++){
		cin >> a[i] ; 
	}
	if(n & 1){
		cout << -1 << '\n' ; 
		return ; 
	}
	for(int i = 1 ; i < n ; i ++){
		if(a[i] == a[i + 1]){
			no[tot].l = i , no[tot ++].r = i + 1 ; 
			i ++ ; 
		}else{
			no[tot].l = i , no[tot ++].r = i ; 
			no[tot].l = i + 1 , no[tot ++].r = i + 1 ; 
			i ++ ; 
		}
	}
	cout << tot << '\n' ; 
	for(int i = 0 ; i < tot ; i ++){
		cout << no[i].l << ' ' << no[i].r << '\n' ; 
	}
}

int main(){	
	std::ios::sync_with_stdio(false) ; 
	std::cin.tie(0) ; 

	int T ; 
	cin >> T ; 
	while(T --){
		solve() ; 
	}

	return 0;
}

C2. Make Nonzero Sum (hard version)

        题目大意:

                题目意思和上题一致,只是序列中出现了0的情况

        分析:

                我们可以发现0怎么变都不会对总价值产生贡献,所以我们还是按照C1的思路解决即可

#include <bits/stdc++.h>

using namespace std ; 
const int N = 200008 ; 
int a[N] ; 
bool vis[N] ; 
bool tmp[N] ; 
void solve(){
	memset(vis , false , sizeof vis) ; 
	memset(tmp , false , sizeof tmp) ; 
	int n ; 
	// puts("-------------------") ; 
	cin >> n ; 
	int sum = 0 ; 
	for(int i = 1 ; i <= n ; i ++){
		cin >> a[i] ; 
		sum += a[i] ; 
	}
	if(sum & 1) {
		cout << -1 << '\n' ; 
		return ; 
	}
	if(sum == 0){
		cout << n << '\n' ; 
		for(int i = 1 ; i <= n ; i ++){
			cout << i << ' ' << i << '\n' ; 
		}
		return ; 
	}
	int cnt = n ; 
	if(sum > 0){
		for(int i = 2 ; i <= n ; i ++){
			if(a[i] == 1 && !tmp[i - 1]){
				// cout << i << '\n' ; 
				sum -= 2 ; 
				vis[i - 1] = true ; 
				tmp[i] = tmp[i - 1] = true ; 
				cnt -- ; 
			}
			if(sum == 0) break ; 
		}
	}else if(sum < 0){
		for(int i = 2 ; i <= n ; i ++){
			if(a[i] == -1 && !tmp[i - 1]){
				sum += 2 ; 
				vis[i - 1] = true ; 
				tmp[i] = tmp[i - 1] = true ; 
				cnt -- ; 
			}
			if(sum == 0) break ; 
		}
	}
	cout << cnt << '\n' ; 
	for(int i = 1 ; i <= n ; i ++){
		if(vis[i]){
			cout << i << ' ' << i + 1 << '\n' ; 
			i ++ ; 
			continue ; 
		}
		cout << i << ' ' << i << '\n' ; 
	}
}

int main(){	
	// std::ios::sync_with_stdio(false) ; 
	// std::cin.tie(0) ; 

	int T ; 
	cin >> T ; 
	while(T --){
		solve() ; 
	}

	return 0;
}

D. Factorial Divisibility

        题目大意:

                给定一个n和x,和一个长度为n的数组,判断a_{1}!+a_{2}!+...+a_{n}!能不能被x!整除

        分析:

                我们可以注意到,例如4!==4\times 3! ,也就是4个3!能够被四整除,也就是说,如果以第i个数为例,如果i-1的个数是i的倍数,那么就所有的i-1加起来就可以被i整除,一下面的例子来理解:

 

 

 

#include <bits/stdc++.h>

using namespace std ; 
const int N = 5e5 + 8 ; 
map<int,int> mp ; 
int a[N] ; 

void solve()
{	
	int n , k ; 
	cin >> n >> k ; 
	for(int i = 1 ; i <= n ; i ++) {
		cin >> a[i] ; 
		mp[a[i]] ++ ; 
	}
	for(int i = 1 ; i < k ; i ++){
		if(mp[i] % (i + 1) == 0)
			mp[i + 1] += mp[i] / (i + 1) ; 
		else {
			puts("NO") ; 
			return ; 
		}
	}
	puts("YES") ; 
}

int main(){	
	std::ios::sync_with_stdio(false) ; 
	std::cin.tie(0) ; 

	solve() ; 

	return 0;
}

EF太菜了不会

水平有限,欢迎指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值