codeforces 22 div2(喔被豹纱了)

A

题目

签到题,利用set的互异性和自动排序就可以

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <bits/stdc++.h>
using namespace std;

int n,ip;
set <int> s;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
for(int i=0;i<n;i++){
cin >> ip;
s.insert(ip);
}
set<int>::iterator it;
it = s.begin();it++;
if(it!=s.end()) cout << *it;
else cout << "NO";
return 0;
}

B

题目

这道题取值范围很小,暴力速解。就是判断一个矩阵里是否含"1",是就pass,否就更行周长c

代码

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
#include <bits/stdc++.h>
using namespace std;

int n,m,c=0;
char room[26][26];
bool check(int x1,int y1,int x2,int y2){
for(int i=x1;i<=x2;i++)
for(int j=y1;j<=y2;j++)
if(room[i][j]=='1') return 0;
return 1;
}

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>room[i][j];
for(int x_1=0;x_1<n;x_1++)
for(int y_1=0;y_1<m;y_1++)
for(int x_2=x_1;x_2<n;x_2++)
for(int y_2=y_1;y_2<m;y_2++)
if(check(x_1,y_1,x_2,y_2)) c=max(c,(x_2-x_1+1+y_2-y_1+1)*2);
cout << c;
return 0;
}

C

题目

一道图论题,此题将我引进了图论的大门。根据情况排除一个顶点(要么排除第一个,要么排除最后一个)后,剩下的顶点往完全图上凑。需要注意的是特殊情况的公式(n-1)*(n-2))/2+1

(WC这题是真的很难读懂啊,用翻译插件翻译成中文也不知道出题人在BB啥)

代码

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
#include <bits/stdc++.h>
using namespace std;

int n,m,v,End,start,pai;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> m >> v;
if(m > ((n-1)*(n-2))/2+1 || m < n-1) cout << -1;
else{
if(v==n){
start=2;End=n;pai=1;
}
else{
start=1;End=n-1;pai=n;
}
cout << v <<' '<< pai<<'\n';
for(int i=start;i<End;i++){
if(m==1) break;
for(int j=i+1;j<=End;j++){
if(m==1) break;
cout << i <<' '<< j << '\n';
m--;
}
}
}
return 0;
}

D

题目

这是一道贪心题。先对每个区间的右端点进行排序,然后取右端点的值,如果该值在下n个区间内,那么下n个区间都是被这个"钉子"钉住的。如果不在下个区间内,则下个区间未被钉住,那么更行该值——取下个区间的右端点。

代码

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;

int n,x1,x2,nail=10001;
vector <int> ans;
struct seg{
int l; int r;
}qu[1001];
bool cpa(seg x,seg y){
return x.r < y.r;
}
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
for(int i=0;i<n;i++){
cin >> x1 >> x2;
if(x1 > x2) swap(x1,x2);
qu[i].l=x1;qu[i].r=x2;
}
sort(qu,qu+n,cpa);
for(int i=0;i<n;i++){
if(nail >= qu[i].l && nail <= qu[i].r) continue;
nail = qu[i].r;
ans.push_back(nail);
}
cout << ans.size() << '\n';
for(auto i:ans) cout << i << ' ';
return 0;
}

codeforces 640 div4

A

题目

签到数学题,就是对多位数进行拆分,例如5108拆成5000,100,8

代码

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
#include <bits/stdc++.h>
using namespace std;

int t,sum,n,a,wei=1;
vector <int> num;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
for(int i=0;i<t;i++){
cin >> n;
wei=1;
while(n){
a = n%10;
if(a!=0) num.push_back(a*wei);
wei *= 10;
n /=10;
}
cout << num.size() << '\n';
for(auto i:num) cout << i <<' ';
cout << '\n';
num.clear();
}
return 0;
}

B

题目

数学题,此题有技巧,找特殊情况。如果a > b并且a-(b-1)是奇数,那么可以凑成特殊情况——b-1个1加上a-(b-1)1;如果a>2b并且a-(b-1)*2是偶数,那么可以凑成特殊情况——b-1个2加上a-(b-1)*2

代码

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
#include <bits/stdc++.h>
using namespace std;

int n,a,b;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
for(int i=0;i<n;i++){
cin >> a >> b;
if(a>=b && (a-b+1)%2==1){
cout << "YES" << '\n';
for(int j=0;j<b-1;j++) cout << 1 << ' ';
cout << a-b+1 << '\n';
}
else if(a>=2*b && (a-(b-1)*2)%2==0){
cout << "YES" << '\n';
for(int j=0;j<b-1;j++) cout << 2 << ' ';
cout << a-(b-1)*2 << '\n';
}
else cout << "NO" << '\n';
}
return 0;
}

C

题目

我了个豆啊又是数学题,数学题就要找寄巧。

将所有正整数从1到+∞ 每n个数分一组,那么每个小组里有n-1个数不能被n整除

这就是关键。注意一下特殊情况(k恰好能整除n-1)就行

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;
int t,n,k,a1,a2;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
for(int i=0;i<t;i++){
cin >> n >> k;
a1= k/(n-1);
a2= k%(n-1);
if(a2 == 0) cout << a1*n+a2-1 << '\n';
else cout << a1*n+a2 << '\n';
}
return 0;
}

D

题目

这题干更是逆天玩意,一看一个不吱声,典型烦人模拟题。

模拟题也不用什么算法,这里注意goto的语句的位置

代码

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
53
54
55
56
#include <bits/stdc++.h>
using namespace std;

int t,n,a,sumr=0,suml=0,r=0,l=0,ci=1,zhi=0;
deque <int> arr;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
for(int i=0;i<t;i++){
cin >> n;
for(int j=0;j<n;j++){
cin >> a;
arr.push_back(a);
}
r += arr.front();
sumr +=r;
arr.pop_front();
while(1){
if(arr.empty()) break;
l=0;zhi=0;
while(l <= r){
if(arr.empty() && zhi==0){
suml+=l;goto en2;
}else if(arr.empty()){
suml+=l;goto en1;
}
l += arr.back();
arr.pop_back();
zhi++;
}
suml+=l;
ci++;
r=0;zhi=0;
while(r <= l){
if(arr.empty() && zhi==0){
sumr+=r;goto en2;
}else if(arr.empty()){
sumr+=r;goto en1;
}
r += arr.front();
arr.pop_front();
zhi++;
}
sumr+=r;
ci++;
}
en2:cout << '\n' << ci<<' '<<sumr<<' '<<suml<<'\n';
arr.clear();sumr=0;suml=0;r=0;l=0;ci=1;
continue;
en1:ci++;
cout << '\n' << ci<<' '<<sumr<<' '<<suml<<'\n';
arr.clear();sumr=0;suml=0;r=0;l=0;ci=1;
}
return 0;
}

算法训练

BFS

马的遍历–洛谷P1143

为减少屏占,题目以图片形式放出

一道经典的BFS搜索题目。

马的前进用BFS+queue解决;到每个可到达点的最少步数,选择用dp递推来累计

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
#include <bits/stdc++.h>
using namespace std;

int n,m,x,y,room[401][401],steps[401][401];
int explore[][2]={1,2,2,1,-1,-2,-2,-1,1,-2,2,-1,-1,2,-2,1};
struct horse{int x;int y;};
#define check(x,y) (x>=0 && x<n && y>=0 && y<m)
void BFS(int sx,int sy){
queue <horse> q;
horse start,next;
start.x=sx; start.y=sy;
q.push(start);
while(!q.empty()){
start=q.front();
q.pop();
for(int i=0;i<8;i++){
next.x = start.x + explore[i][0];
next.y = start.y + explore[i][1];
if(check(next.x,next.y) && room[next.x][next.y]==0){
room[next.x][next.y]=1;
steps[next.x][next.y]=steps[start.x][start.y]+1;
q.push(next);
}
}

}
}

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> m >> x >> y;
x--; y--;
fill_n(&steps[0][0],401*401,-1);
room[x][y]=1;
steps[x][y]=0;
BFS(x,y);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cout << steps[i][j] << ' ';
}
cout << '\n';
}
return 0;
}

DP

硬币问题

1.最小硬币问题

题目描述:

有n种硬币,面值分别为v1,v2,…,vn,数量无限。输入非负整数s,选用硬币,使其和为s。要求输出最少的硬币组合。

这是一道DP题目,minnum[j]表示要凑到 j 元所需最小的硬币数量。

状态转移方程为minnum[j]=min(minnum[j],minnum[j-money[i]]+1)

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
using namespace std;

int value,minnum[251],money[5]={1,5,10,20,50};

void mincoin(int *value){
for(int i=0;i<5;i++)
for(int j=money[i];j<=*value;j++)
minnum[j]=min(minnum[j],minnum[j-money[i]]+1);
}

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
fill_n(&minnum[0],251,INT_MAX);
minnum[0]=0;
cin >> value;
mincoin(&value);
cout << minnum[value] <<'\n';
return 0;
}

硬币问题未完待续…