A - Dreamoon and Ranking Collection
1.题意
小明参加了n场比赛,名次分别是ai ,求他再参加 x 场比赛后,所能达到的名次的最大值(数字最大),要求这个名次之前的所有名次都曾获得过。
2.题解
用一个数组记录是否获得过此名次,然后遍历所有名次,没有获得就 x - - ,再注意下细节就过了。
3.代码
#include<bits/stdc++.h> #define ll long long using namespace std; int t; int main() { ios::sync_with_stdio(false); cin >> t; while(t--) { int n, x; cin >> n >> x; int a[1000] = {0}; for(int i = 1; i <= n; i++) { int temp; cin >> temp; a[temp] = 1; } // for(int i = 1; i <= n; i++) { // cout << a[i] << ' '; // } int ans = 1; for(int i = 1; i <= 1000 && x >= 0; i++) { if(a[i] == 0) { x--; } ans = i; } cout << ans - 1 << endl; } return 0; }
B - Dreamoon Likes Permutations
1.题意
给定一个数列,要求把此数列砍一刀,分割成两个数列,且两个数列的任意一个数列都满足数字不重复、包含从1到数列长度的每一个数,求有几种分割方法,输出分割出的两个数列长度。
2.题解
砍一刀并且要求两个序列从1开始连续不重复,即两个序列的最大值就是它们的序列长度,原序列的最大值肯定在其中一个序列中是最大值,最大值所在的那个序列长度必须是max才有可能满足题意,因为不知道max 在原序列哪个位置,所以最多有两种分割方式:max ,n - max 和 n - max ,max ,分别检测两种情况的两个序列是否满足条件,我检查的方法是对两个序列排序,判断是否ai == i 。另外,如果max 是n 的一半,最多一种切割方式。
3.代码
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 2e6 + 5; int t, n; int a[maxn]; int b[maxn]; int check(int p) { for(int i = 1; i <= p; i++) { if(a[i] != i) { return 0; } } for(int i = p + 1; i <= n; i++) { if(a[i] != i - p) { return 0; } } return 1; } int main() { ios::sync_with_stdio(false); cin >> t; while(t--) { int mmax = 1; cin >> n; for(int i = 1; i <= n; i++) { cin >> a[i]; b[i] = a[i]; mmax = max(mmax, a[i]); } int flag1 = 0; int flag2 = 0; sort(a + 1, a + 1 + mmax); sort(a + 1 + mmax, a + 1 + n); // for(int i = 1; i <= n; i++) { // cout << a[i] << ' '; // } // cout << endl; flag1 = check(mmax); //cout << "flag1 = " << flag1 << endl; for(int i = 1; i <= n; i++) { a[i] = b[i]; } sort(a + 1, a + 1 + n - mmax); sort(a + 1 + n - mmax, a + 1 + n); // for(int i = 1; i <= n; i++) { // cout << a[i] << ' '; // } // cout << endl; flag2 = check(n - mmax); //cout << "flag2 = " << flag2 << endl; if(flag1 || flag2) { if(mmax * 2 == n) { cout << 1 << endl; cout << mmax << ' ' << n - mmax << endl; } else { if(flag1 && flag2) { cout << 2 << endl; cout << mmax << ' ' << n - mmax << endl; cout << n - mmax << ' ' << mmax << endl; } else if(flag1) { cout << 1 << endl; cout << mmax << ' ' << n - mmax << endl; } else { cout << 1 << endl; cout << n - mmax << ' ' << mmax << endl; } } } else { cout << 0 << endl; } } return 0; }
C - Exercising Walk
1.题意
给定一个矩阵,边界为x1,x2,y1,y2,初始点为x,y,问是否能在这个矩阵中完成向左走a步,向右走b步,向下走c步,向上走d步。
2.题解
水平位置走 a - b 步,竖直位置走 c - d 步,判断走后是否在范围内即可,另外如果 x1 == x2,a - b ==0 但 a != 0,也没法完成,竖直位置同理。
3.代码
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 2e6 + 5; int t; int main() { ios::sync_with_stdio(false); cin >> t; while(t--) { int a, b, c, d; cin >> a >> b >> c >> d; int x, y, x1, y1, x2, y2; cin >> x >> y >> x1 >> y1 >> x2 >> y2; int xx = x + b - a; int yy = y + d - c; if(xx < x1 || xx > x2 || yy < y1 || yy > y2) { cout << "No" << endl; } else if(x1 == x2 && a || y1 == y2 && c) { cout << "No" << endl; } else { cout << "Yes" << endl; } } return 0; }
D - Composite Coloring
1.题意
给定 n 个合数,要求用 m 种颜色把这 n 个数染色,如果两个数的最大公约数大于1,那么这两个数可以染同一种颜色,不必最小化 m ,输出一种解即可。
2.题解
因为全是合数,所以可以分解出质因子,ai <= 1000,根下1000约等于31,而1到31的质因子正好有11个,分别是2,3,5,7,11,13,17,19,23,29,31,所以按这些质因子分组即可,最后把结果处理一下(例:把2 9 3 5 3 变成 1 2 3 4 3)。
3.代码
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 2e6 + 5; int t; int main() { ios::sync_with_stdio(false); cin >> t; while(t--) { int n; cin >> n; int a[n + 1] = {0}; for(int i = 1; i <= n; i++) { cin >> a[i]; } int k = 0; int num[11] = {2,3,5,7,11,13,17,19,23,29,31}; int book[11] = {0}; vector<int> ans; for(int i = 1; i <= n; i++) { for(int j = 0; j < 11; j++) { if(a[i] % num[j] == 0) { //cout << j << ' '; book[j] = 1; ans.push_back(j + 1); break; } } } int cnt = 0; for(int i = 0; i < 11; i++) { if(book[i] == 1) { cnt++; } } cout << cnt << endl; int res[12] = {0}; int x = 1; for(vector<int>::iterator it = ans.begin(); it < ans.end(); it++) { if(res[*it] == 0) { res[*it] = x; x++; } } for(vector<int>::iterator it = ans.begin(); it < ans.end(); it++) { if(it == ans.begin()) { cout << res[*it]; } else { cout << ' ' << res[*it]; } } cout << endl; } return 0; }
E - K-th Beautiful String
1.题意
给定两个正整数 n,k,要求用 n - 2个 a 和 两个 b 构造一个按字典排序第 k 小的字符串。
2.题解
任意指定一个 n ,写下所有排列情况,可以找到规律。先找第一个 b ,可以从 n - 1向前枚举,每次枚举有 n - i 种情况,如果 k <= n - i,第一个 b 就确定下来了,再找第二个 b,在第一个 b 后面的第 n - i - k + 1个字符(k是更新后的),否则 k -= n - i 。用一个变量记录输出了多少个子符。
3.代码
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 2e6 + 5; int t; int main() { ios::sync_with_stdio(false); cin >> t; while(t--) { int n, k; cin >> n >> k; int cnt = 0; for(int i = n - 1; i > 0; i--) { if(k <= n - i) { for(int j = 1; j < i; j++) { cout << 'a'; } cout << 'b'; cnt += i; for(int j = 1; j <= n - i - k; j++) { cout << 'a'; } cout << 'b'; cnt += n - i - k + 1; for(int j = cnt; j < n; j++) { cout << 'a'; } break; } else { k -= n - i; } } cout << endl; } return 0; }
F - Carousel
1.题意
n个旋转木马围成一个环,旋转木马的类型是它们上面的数字,现在要给所有木马染色,要求不同类型的相邻木马不能同色,最小化颜色使用数,输出一种染色方案。
2.题解
如果所有木马类型一样,都涂同一种颜色;如果 n 为偶数,两种颜色间隔涂即可;如果 n 为奇数,但是其中有两个木马类型相同且相邻,则把它俩看成一个,再按偶数涂即可;如果 n 为奇数,但是其中没有两个木马类型相同且相邻,那就按偶数涂,把最后一个涂上第三种颜色。
3.代码
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn = 2e6 + 5; int t; int main() { ios::sync_with_stdio(false); cin >> t; while(t--) { int n; cin >> n; int a[n + 1]; bool flag = true; for(int i = 1; i <= n; i++) { cin >> a[i]; if(a[i] != a[1]) { flag = false; } } if(flag) { cout << 1 << endl; for(int i = 1; i <= n; i++) { cout << 1 << ' '; } } else if(n % 2 == 0) { cout << 2 << endl; for(int i = 1; i<= n; i++) { if(i % 2 == 0){ cout << 2 << ' '; } else { cout << 1 << ' '; } } } else { int pos = 0; if(a[1] == a[n]) { pos = n; } if(pos != n) { for(int i = 1; i < n; i++) { if(a[i] == a[i + 1]) { pos = i; break; } } } if(pos == 0) { cout << 3 << endl; for(int i = 1; i< n; i++) { if(i % 2 == 0){ cout << 1 << ' '; } else { cout << 2 << ' '; } } cout << 3; } else if(pos == n) { cout << 2 << endl; cout << 2 << ' '; for(int i = 2; i < n; i++) { if(i % 2 == 0){ cout << 1 << ' '; } else { cout << 2 << ' '; } } cout << 2 << ' '; } else { cout << 2 << endl; for(int i = 1; i < n; i++) { if(i == pos) { if(i % 2 == 0){ cout << 1 << ' '; cout << 1 << ' '; } else { cout << 2 << ' '; cout << 2 << ' '; } } else { if(i % 2 == 0){ cout << 1 << ' '; } else { cout << 2 << ' '; } } } } } cout << endl; } return 0; }