比赛链接:Dashboard - Codeforces Round #829 (Div. 2) - Codeforces
目录
C1. Make Nonzero Sum (easy version)
C2. Make Nonzero Sum (hard version)
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;
}