CodeForce刷题表

Day13

1611A - Make Even

题意:

给定一个数让他变成偶数。

可以进行的操作是:选定k,把1到k的数字倒置。

思路:

如果最开始就是偶数,答案是0

如果第一个数字是偶数,直接倒置,答案是1

如果中间有偶数,先倒置一次到第一个数字,然后再整体倒置,答案是2

如果没有偶数,答案是-1

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const ll mod = 1e9+7;
bool hhead(int x) {
int t;
while(x) {
t = x%10;
x/=10;
}
if(t%2==0)
return true;
else
return false;
}
bool Two(int x) {
int t=0;
while(x) {
if((x%10)%2==0)
t = 1;
x/=10;
}
if(t)
return true;
else
return false;
}
int main(){
int _;cin>>_;
while(_--) {
int x;
cin>>x;
if(x%2==0)
cout<<0<<endl;
else if(hhead(x))
cout<<1<<endl;
else if(Two(x))
cout<<2<<endl;
else
cout<<-1<<endl;
}
return 0;
}

总结:

我这样写是麻烦了的,可以直接用字符串来做。

1611B - Team Composition: Programmers and Mathematicians

题意:

有a个程序员和b个数学家,可以组成几个四人队(每个队伍至少有一个程序员/数学家)

思路:

先看看a+b人最多能组成多少个队(k个队。

再看看a和b是不是比k大,是的话就输出k,不是就输出较小的一个

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const ll mod = 1e9+7;
int main(){
int _;cin>>_;
while(_--) {
ll a,b,t;
cin>>a>>b;
t = (a+b)/4;
if(a>t && b>t)
cout<<t<<endl;
else
cout<<min(a,b)<<endl;
}
return 0;
}

总结:

ez

1611C - Polycarp Recovers the Permutation

题意:

给你一组数[1 , n],左端和右端的数进行比较,把较小的一个数放在新的数组的左端/右端(取决于该数在左端还是右端)。最后剩下最大的数可以放在左边或者右边。

现在给你一个结果数组,问一种可能的初始数组。

思路:

先查看最左端或者最右端是不是n,如果都不是直接输出-1.

如果是就把最大的数放在最右边,其他的数倒着输出一遍

因为: 2 3 1 4 最右边的是最大的,其他的肯定比他小,那么每次都会把数字往左放,那么得到的就是倒序 1 3 2 最后4可以放在左边也可以放在右边 1 3 2 4。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const ll mod = 1e9+7;
int a[N];
int main(){
int _;cin>>_;
while(_--) {
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
if(a[1]!=n && a[n]!=n)
cout<<-1<<endl;
else {
if(a[1]==n) {
for(int i=n;i>=2;i--)
cout<<a[i]<<" ";
cout<<a[1]<<endl;
}
else if(a[n]==n) {
for(int i=n-1;i>=1;i--)
cout<<a[i]<<" ";
cout<<a[n]<<endl;
}
}
}
return 0;
}

总结:

还行

1611D - Weights Assignment For Tree Edges

题意:

给你n个节点,告诉你每个节点的父亲节点是谁,再给你一个节点到根的权值排序,让你写出一组可能的节点到父亲节点的权值。

根到节点不能有相同的权值。

思路:

记录每个节点的父亲,以及是否出现过。

根据节点到根的权值排序,假设节点到根的权值为1 - n(因为不能相同)

如果一个节点的父亲节点没有出现过,但是出现了儿子,那么输出-1。

出现以后用所给的节点到根的权值 减去 父亲节点到根的权值 得到 节点到父亲节点的权值。

按顺序输出答案。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
const ll mod = 1e9+7;
ll f[N];//记录父亲
ll num[N];//记录给定数值
ll rel[N];
int k[N];//是否出现过
ll dui[N];
int main(){
int _;cin>>_;
while(_--) {
memset(k,0,sizeof k);
int n,x,root;
cin>>n;
for(int i=1;i<=n;i++) {
cin>>x;
f[i] = x;
if(i == x)
root = x;
}
for(int i=1;i<=n;i++)
cin>>dui[i];
if(dui[1] != root) {
cout<<-1<<endl;
continue;
}
k[root] = 1;
num[root] = 0;
rel[root] = 0;
for(int i=2;i<=n;i++)
num[dui[i]] = i;
int kk=0;
for(int i=2;i<=n;i++) {
if(k[f[dui[i]]]==0) {
kk=1;
break;
}
k[dui[i]] = 1;
rel[dui[i]] = num[dui[i]] - num[f[dui[i]]];
}
if(kk==1)
cout<<-1;
else
for(int i=1;i<=n;i++)
cout<<rel[i]<<" ";
cout<<endl;
}
return 0;
}

总结:

别想多,别想的高深莫测