Codeforces Round #829 (Div. 2) A~D

比赛链接:Dashboard - Codeforces Round #829 (Div. 2) - Codeforces

目录

A. Technical Support 

B. Kevin and Permutation 

C1. Make Nonzero Sum (easy version) 

C2. Make Nonzero Sum (hard version) 

D. Factorial Divisibility 


A. Technical Support 

题意:给定一个由QA组成的字符串,Q表示问题,A表示回答,要求每一个Q后面都能对应至少一个A。

思路:从后往前遍历,遇到‘Q’的时候判断‘A’的个数是否大于‘Q’,若不是则输出NO。

#define _CRT_SECURE_NO_WARNINGS 1
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<math.h>
#define FOR(a,b) for(int i=a;i<=b;i++)
#define ROF(a,b) for(int i=a;i>=b;i--)
#define FORj(a,b) for(int j=a;j<=b;j++)
#define ROFj(a,b) for(int j=a;j>=b;j--)
#define FORk(a,b) for(int k=a;k<=b;k++)
#define ROFk(a,b) for(int k=a;k>=b;k--)
#define mem(i,a) memset(i,a,sizeof(i))
#define ll long long
#define inf 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int  long long
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pi acos(-1.0)
#define endl '\n'
using namespace std;
const int maxn = 5e6 + 5;
void solve() {
	int n,A=0,Q=0;
	string s;
	cin >> n >> s;
	ROF(n - 1, 0) {
		if (s[i] == 'A')A++;
		else Q++;
		if (s[i] == 'Q' && A < Q) {
			no;
			return;
		}
	}
	yes;
}
signed main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
		int _;
		cin >> _;
		while (_--)
	solve();
	return 0;
}

B. Kevin and Permutation 

题意:给定数组长度n,请构造一个排列使得两个相邻元素差的最小值最大。

思路:我们可以俩俩一组构造,像n/2+1, 1, n/2 + 2, 2......这样子,若数组长度为奇数,我们只用将n放到数组最后即可。

#define _CRT_SECURE_NO_WARNINGS 1
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<math.h>
#define FOR(a,b) for(int i=a;i<=b;i++)
#define ROF(a,b) for(int i=a;i>=b;i--)
#define FORj(a,b) for(int j=a;j<=b;j++)
#define ROFj(a,b) for(int j=a;j>=b;j--)
#define FORk(a,b) for(int k=a;k<=b;k++)
#define ROFk(a,b) for(int k=a;k>=b;k--)
#define mem(i,a) memset(i,a,sizeof(i))
#define ll long long
#define inf 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int long long
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pi acos(-1.0)
#define endl '\n'
using namespace std;
const int maxn = 2e5 + 5;
void solve() {
	int n;
	cin >> n;
	FOR(1,n/2)  cout << i + n / 2 <<" " << i << " ";
	if(n%2)cout<<n;
	cout<<endl;
}
signed main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	int _;
	cin >> _;
	while (_--)
		solve();
	return 0;
}

C1. Make Nonzero Sum (easy version) 

题意:给定一个[-1, 1]组成的数组,将该数组拆分成若干区间,每一个区间的价值为a[l]-a[l+1]+a[l+2]-a[l+3]......a[r]。需要我们构造一个划分区间的方法使得总价值为0。

思路:若1和-1的总数目为奇数则构造不了使得总价值为0的方法,因为划分区间在本质上只是能吧一些-1变成1,把一些1变成-1,或者不变。所以每次总价值只会-2或者+2,若n为奇数那么初始的总价值也为奇数,改变区间对应改变的总价值也只会是偶数,那么总价值永远到不了0。

当n为偶数时,我们可以两两分组,每组选择两次长度为1的区间,或一次长度为2的区间,若选择两次长度为1的区间会使得总价值不变,选择一次长度为2的区间会使得总价值-2或者总价值+2,我们最多选择n/2组,所以当n为偶数的时候必有解。

ps:C题我写的代码比较乱,建议看别人的代码或者自己写。

#define _CRT_SECURE_NO_WARNINGS 1
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<math.h>
#define FOR(a,b) for(int i=a;i<=b;i++)
#define ROF(a,b) for(int i=a;i>=b;i--)
#define FORj(a,b) for(int j=a;j<=b;j++)
#define ROFj(a,b) for(int j=a;j>=b;j--)
#define FORk(a,b) for(int k=a;k<=b;k++)
#define ROFk(a,b) for(int k=a;k>=b;k--)
#define mem(i,a) memset(i,a,sizeof(i))
#define ll long long
#define inf 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int long long
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pi acos(-1.0)
#define endl '\n'
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn];
pair<int, int>b[maxn];
void solve() {
	int n, z = 0, f = 0, k = 0;
	cin >> n;
	FOR(1, n) {
		cin >> a[i];
		if (a[i] == 1)z++;
		else f++;
	}
	if (z == f) {
		cout << n << endl;
		FOR(1, n)cout << i << " " << i << endl;
		return;
	}
	if (n % 2) {
		cout << -1 << endl;
		return;
	}
	if (z > f) {
		FOR(1, n - 1) {
			if (a[i + 1] == 1) {
				b[++k].first = i, b[k].second = i + 1;
				z--;
				f++;
				i++;
			} else 	b[++k].first = i, b[k].second = i;
			if (z == f)break;
		}
	} else {
		FOR(1, n - 1) {
			if (a[i + 1] == -1) {
				b[++k].first = i, b[k].second = i + 1;
				f--;
				z++;
				i++;
			} else 	b[++k].first = i, b[k].second = i;
			if (z == f)break;
		}
	}
	cout << k + n - b[k].second << endl;
	FOR(1, k)cout << b[i].first << " " << b[i].second << endl;
	FOR(b[k].second + 1, n)cout << i << " " << i << endl;
}
signed main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	int _;
	cin >> _;
	while (_--)
		solve();
	return 0;
}

C2. Make Nonzero Sum (hard version) 

题意:给定一个[-1, 0,1]组成的数组,将该数组拆分成若干区间,每一个区间的价值为a[l]-a[l+1]+a[l+2]-a[l+3]......a[r]。需要我们构造一个划分区间的方法使得总价值为0。(和C1相比就是数组中除了1和-1多了0)

思路:和C1大同小异,也是两个不为0的数组两个为一组,我们需要先获取两个不为0的数字的下标,就可以构造出每组中第二个数字取反的区间方法了,同样每次操作能使总价值+2或者-2。

#define _CRT_SECURE_NO_WARNINGS 1
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<math.h>
#define FOR(a,b) for(int i=a;i<=b;i++)
#define ROF(a,b) for(int i=a;i>=b;i--)
#define FORj(a,b) for(int j=a;j<=b;j++)
#define ROFj(a,b) for(int j=a;j>=b;j--)
#define FORk(a,b) for(int k=a;k<=b;k++)
#define ROFk(a,b) for(int k=a;k>=b;k--)
#define mem(i,a) memset(i,a,sizeof(i))
#define ll long long
#define inf 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int long long
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pi acos(-1.0)
#define endl '\n'
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn];
pair<int, int>b[maxn];
void solve() {
	int n, z = 0, f = 0, k = 0;
	cin >> n;
	FOR(1, n) {
		cin >> a[i];
		if (a[i] == 1)z++;
		else if(a[i]==-1)f++;
	}
	if (z == f) {
		cout << n << endl;
		FOR(1, n)cout << i << " " << i << endl;
		return;
	}
	if ((z+f)% 2) {
		cout << -1 << endl;
		return;
	}
	int p1= 1,p2=2;
	if (z > f) {
		while(p2<=n) {
			while (!a[p2] && p2 <= n)p2++;
			if (a[p2] == 1) {
				if ((p2 - p1) % 2)b[++k].first = p1, b[k].second = p2;
				else {
					b[++k].first = p1, b[k].second = p1;
					b[++k].first = p1 + 1, b[k].second = p2;
				}
				z--, f++;
			} else {
				if ((p2 - p1) % 2) {
					b[++k].first = p1, b[k].second = p1;
					b[++k].first = p1 + 1, b[k].second = p2;
				} else {
					b[++k].first = p1, b[k].second = p2;
				}
			}
			if (z == f)break;
			p1 = p2 + 1;
			p2=p1+1;
		}
	} else {
		while (p2 <= n) {
			while (!a[p2] && p2 <= n)p2++;
//			 cout<<p1<<" "<<p2<<" "<<a[p1]<<" "<<a[p2]<<endl;
			if (a[p2] == -1) {
				if ((p2 - p1) % 2)b[++k].first = p1, b[k].second = p2;
				else {
					b[++k].first = p1, b[k].second = p1;
					b[++k].first = p1 + 1, b[k].second = p2;
				}
				z++, f--;
			} else {
				if ((p2 - p1) % 2) {
					b[++k].first = p1, b[k].second = p1;
					b[++k].first = p1 + 1, b[k].second = p2;
				} else {
					b[++k].first = p1, b[k].second = p2;
				}
			}
			if (z == f)break;
			p1 = p2 + 1;
			p2=p1+1;
		}
	}
	cout << k + n - b[k].second << endl;
	FOR(1, k)cout << b[i].first << " " << b[i].second << endl;
	FOR(b[k].second + 1, n)cout << i << " " << i << endl;

}
signed main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	int _;
	cin >> _;
	while (_--)
		solve();
	return 0;
}

D. Factorial Divisibility 

题意:给定一个长度为n的数组和k,判断!k是否整除(!a1 + !a2 + !a3 + !a4... + !an)。

思路:我们可以发现一个规律:1!+1!=2!,2!+2!+2!=3!,3!+3!+3!+3!=4!......

 所以可得出n个x!可以转化为n/(x+1)个(x+1)!,所以我们从低位到高位累加,利用mp[i] % (i + 1)是否等于0,来判断每位能不能将数字全部转化,若不能被全部转化就说明了不能被整除。

#define _CRT_SECURE_NO_WARNINGS 1
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<math.h>
#define FOR(a,b) for(int i=a;i<=b;i++)
#define ROF(a,b) for(int i=a;i>=b;i--)
#define FORj(a,b) for(int j=a;j<=b;j++)
#define ROFj(a,b) for(int j=a;j>=b;j--)
#define FORk(a,b) for(int k=a;k<=b;k++)
#define ROFk(a,b) for(int k=a;k>=b;k--)
#define mem(i,a) memset(i,a,sizeof(i))
#define ll long long
#define inf 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int unsigned long long
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pi acos(-1.0)
#define endl '\n'
using namespace std;
const int maxn = 5e6 + 5;
map<int, int>a;
void solve() {
	int n, k;
	cin >> n >> k;
	FOR(1, n) {
		int x;
		cin >> x;
		a[x]++;
	}
	FOR(1, k-1) {
		if (a[i] % (i + 1)) {
			no;
			return;
		}
		a[i + 1] += a[i] / (i + 1);
	}
	yes;
}
signed main() {
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	//	int _;
	//	cin >> _;
	//	while (_--)
	solve();
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值