Codeforces Round #671(Div.2)
题目 | A | B | C | D | E | F |
---|---|---|---|---|---|---|
solved | ✔ | ⚪ | - | ✔ | - | - |
✔比赛时通过,⚪比赛时尝试了但是未通过
总结:
- 读题! 大佬们两分钟就把A题做出来了,我过了半小时才发现题目读错了。早上起来补题的时候又发现B题读错了。。。
A. Digit Game
题意: T组数据,每组数据给出一个长度为n的数组,游戏为玩家一和玩家二两人轮流给数组中的数字打上标记。规则为从玩家一开始,两人轮流;玩家一只能标记奇数位上的数字,玩家二只能标记偶数位上的数字。直到数组中只剩一个数字未标记时,游戏结束。剩下的数字是奇数,则输出1,代表玩家一获胜;是偶数则输出2,代表玩家二获胜。假设两个玩家都是聪明的,每一步都是对自己利益最大化的,根据给出的数组判断最后的获胜人选。
题解:
- 数组中只有一个数字: 游戏开始即结束,这个数是奇数则直接输出1,偶数则输出2。
- 数组中有奇数个数字: 奇数位上的数字多于偶数位上的数字,主动权掌握在玩家一手上,只要奇数位上出现过奇数,玩家一就能稳赢。
- 数组中有偶数个数组: 奇数位上的数字多余偶数位,但是应为游戏从玩家一开始,所以玩家一比玩家二要多标记一个数字。主动权掌握在玩家二手上,只要偶数位上出现过偶数,玩家二稳赢饿。
#include<bits/stdc++.h>
using namespace std;
int _T, n, m;
char s[1005];
int main(){
scanf("%d", &_T);
while(_T--){
scanf("%d", &n);
scanf("%s", s);
int len = strlen(s);
int cnt = 0, count = 0;
for(int i = 0; i < len; i++){
if((s[i] - '0') % 2 == 1 && (i + 1) % 2 == 1) cnt++;
else if((s[i] - '0') % 2 == 0 && (i + 1) % 2 == 0) count++;
}
if(n == 1){
if(cnt) printf("1\n");
else printf("2\n");
}else if(n % 2 == 1){
if(cnt) printf("1\n");
else printf("2\n");
}else{
if(count) printf("2\n");
else printf("1\n");
}
}
return 0;
}
B. Stairs
题意: 楼梯的台阶数不限,但是第i列应该是由i ii个方块叠加形成。如果n阶楼梯由单元格组成的n个不相交的正方形覆盖,则称为nice楼梯(看图中花花绿绿的颜色,一共有7个正方形,同时楼梯也是7阶的)。
题解: 正确理解题意之后,要找到其中的规律也就不难了。其实一个新的nice楼梯,是在上一个n阶的nice楼梯的旁边,放置一个(n+1)*(n+1)的正方形,然后再正方形之上,再放置一个n阶楼梯,就构成了新的(2*n+1)阶的nice楼梯。由此很容易可以得出,第 i 个nice楼梯的方块数为i * (i + 1) / 2
.
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
int _T;
ll x;
void run(){
cin >> x;
int cnt = 0;
for(ll i = 1; ; ){
ll tem = (i + 1) * i / 2;
if(x < tem) break;
x -= tem;
cnt++;
i = i * 2 + 1;
}
cout << cnt << endl;
}
int main(){
IOS;
cin >> _T;
while(_T--) run();
return 0;
}
C. Killjoy
题意: 有n个分数以及一个病毒分数,每场比赛可以改变这些分数值,要求是改变量之和为零,与病毒分数相同的分值则会感染病毒,此种病毒具有传染性。问最少需要几场比赛可以感染所有的分数。、
题解: 可以先考虑几种特殊情况:
- 所有分值都等于病毒分数:那一场比赛都不需要,直接输出零就可以了。答案是
0
. - 这些分数的平均值等于病毒分数:题目要求每场比赛的该变量之和为零,如果平局之等于病毒分数,我们就可以只用一场比赛就感染所有的分数。答案是
1
. - 这些分数中,出现过病毒分值: 相当于在固定的病毒源基础上,我们可以通过改变这个与病毒分数相等发分值,实现多个不同分值的病毒源。具体分值不需要我们去计算,但是我们仍然能够想到,在这种情况下,一场比赛就能感染所有分数。答案是
1
. - 这些分数中没有出现过病毒分值:同上,当我们通过一场比赛获得多个不同分值的病毒源之后,我们能够很轻易地再用一场比赛来感染所有的分数。答案是
2
.
综上可得程序:
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
int _T, n, x, val;
void run(){
cin >> n >> x;
int cnt = 0, sum = 0;
for (int i = 0; i < n; ++i) {
cin >> val;
cnt += (val == x);
sum += val;
}
if (cnt == n)
cout << 0 << '\n';
else if (cnt > 0)
cout << 1 << '\n';
else if (sum == n * x)
cout << 1 << '\n';
else
cout << 2 << '\n';
}
int main(){
IOS;
cin >> _T;
while(_T--) run();
return 0;
}
D1. Sage’s Birthday (easy version)、D2. Sage’s Birthday (hard version)
题意: 给定一个长度为n的数组,要求将数组排列成凹口最多的情况,并输出凹口数量和排列后的数组。数组中某一位的数字小于相邻的两个数视为凹口。D1中保证所有的数字均不相等,D2中可能会出现相同的数字。
题解: D1和D2的区别就在于会不会出现重复的数字。其实第一想法就是,将数组排好序,然后连头一次穿插起来,但是这样是不难解决D2的。所以办法是,还是先将数组排好序,将数组对半分成两段,然后依次取出每段的最前面的数字,构成新的数组——就是凹口最多的数组,而凹口数量还需要重新数。
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 1e5 + 10;
int n, a[N];
vector<int> v;
void run(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
if(n % 2 == 0) v.push_back(a[n / 2]);
for(int i = 1; i <= (n - 1) / 2; i++){
v.push_back(a[n / 2 + i]);
v.push_back(a[i]);
}
v.push_back(a[n]);
int cnt = 0;
for(int i = 1; i < v.size() - 1; i++)
if(v[i] < v[i - 1] && v[i] < v[i + 1])
cnt++;
cout << cnt << endl;
for(auto i : v) cout << i << " ";
}
int main(){
IOS;
run();
return 0;
}