注:题解给出顺序按(自认为的)题目难度顺序排序
B:ICPC与小鹿的差旅费用规划
最基础的A+B问题,注意题目给出的票价是单程票价,应计算两次,同时注意题目中给出的a和b的最大值均为 $2 \cdot 10^{15}$ ,应使用long long
类型存储
1
2
3
4
5
6
7
8
9
10
11
12
13
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
long long a,b;
cin>>a>>b;
cout<<a*2+b<<endl;
}
return 0;
}
D:百度之星与小鹿的铁牌
根据题干,可知除格子1,2以外,其他格子的可能路线均为其左侧两格子可能路线之和。再对样例稍加观察后,不难发现本题其实就是斐波那契数列的换皮版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int a[n+1];
a[0]=0;a[1]=1;
for(int i=2;i<=n;i++) a[i]=a[i-1]+a[i-2];
cout<< a[n] <<endl;
}
return 0;
}
E:蓝桥杯与鹿与小面包
因为每次必须删除连续的 $k$ 个数,数组中的数某个一项如果能够在最终被保留,那么其左侧和右侧的项的数量都应恰好为 $k$ 的倍数,又因题目限定 $N$ $mod$ $k$ $=$ $1$ ,所以该条件前半段满足时后半段自然满足,因此,我们只需要遍历所有左侧项数等于k的倍数的项,并取最大值即可
1
2
3
4
5
6
7
8
9
10
11
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k;
cin>>n>>k;
int a[n],ans=0;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i+=k) ans=max(ans,a[i]);
cout<<ans;
}
A:网络竞赛平台与小鹿与正在检验你是否是真人请稍后
首先,统计每个给出的数中每一个数字出现了多少次,将其存储于数组中,随后每次从其中取出一个最小的数字,直到数组被取完即可。需要注意的是,对第一次取数不能取0,此处应给出特判。
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
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int num[15]={0};
string s;
cin>>s;
for(int i=0;i<s.size();i++)num[s[i]-'0']++;
for(int i=1;i<=9;i++){
if(num[i]){
cout<<i;
num[i]--;
break;
}
}
for(int j=1;j<s.size();j++){
for(int i=0;i<=9;i++){
if(num[i]){
cout<<i;
num[i]--;
break;
}
}
}
cout<<endl;
}
}
G:天梯赛与小鹿与字符串维护
正如标题所说,这题的核心就是字符串维护,因为N较小,直接使用暴力方法即可通过本题
如果使用C的char数组解题的话,在处理这些操作时恐怕会麻烦颇多,也相对容易写出很多奇怪的bug,如果这题写不出来的话就去学学string的用法吧,绝对会很有用的
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
#include<bits/stdc++.h>
using namespace std;
int a[26];
long long getsum(string s){
long long res=0;
for(int i=0;i<s.size();i++) res+=a[s[i]-'a'];
return res;
}
int main(){
int n;
cin>>n;
string s;
cin>>s;
for(int i=0;i<26;i++) cin>>a[i];
int q;
cin>>q;
while(q--){
int orp;
cin>>orp;
if(orp==1){
string ss;
cin>>ss;
s=s+ss;
}
if(orp==2){
cout<<getsum(s)<<endl;
}
if(orp==3){
int l,r;
cin>>l>>r;
s.erase(l-1,r-l+1);
}
}
return 0;
}
F:睿抗与小鹿的贪心消消乐
此题有两个难点,如何判断三点相邻和如何处理万能符号.
在经过对出题人的拷打过后,如何判断三个点相邻的方法已经作为解释写明在题干上了,先判断是否存在横坐标或纵坐标均相等,再判断另一者是否公差为1,考虑到三个点均不相同,判断其中最大者减最小者是否为2即可
对于.
这一万能符号,我们可以考虑在判断是否能消除时,使用三个变量存储RGB各自的数量,.
同时视作R、G、B,之后判断是否有其一等于3即可
本题如果能学会C++中STL容器里的string
的一些基础用法的话,写起来想必会舒服非常多
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
57
58
59
60
61
62
63
64
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
string s[n+1];
for(int i=1;i<=n;i++){
cin>>s[i];
s[i]='x'+s[i]; //这个x是个占位符,保证原字符串从下标1处开始
}
int q;
cin>>q;
while(q--){
int opr;
cin>>opr;
if(opr==1){
int x[4],y[4];
cin>>x[1]>>y[1]>>x[2]>>y[2]>>x[3]>>y[3];
int r=0,g=0,b=0,lk=0;
//lk用于判断三个坐标是否相邻且成行
if(x[1]==x[2]&&x[1]==x[3]){
if( max({y[1],y[2],y[3]}) - min({y[1],y[2],y[3]}) ==2)
lk=1;
}
if(y[1]==y[2]&&y[1]==y[3]){
if( max({x[1],x[2],x[3]}) - min({x[1],x[2],x[3]}) ==2)
lk=1;
}
if(!lk){
cout<<"NO"<<endl;
continue;
}
for(int i=1;i<4;i++){
if(s[x[i]][y[i]]=='R')
r++;
if(s[x[i]][y[i]]=='G')
g++;
if(s[x[i]][y[i]]=='B')
b++;
if(s[x[i]][y[i]]=='.')
r++,g++,b++;
}
if(r==3||g==3||b==3) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else{
int x,y;
string z;
cin>>x>>y>>z;
//此处用字符串存储修改是为了避免读入多余的空格与换行
s[x][y]=z[0];
}
}
}
C:CCPC与饭后消食的小鹿
如果用暴力做法的话,每一步在上一步的基础上延申出两种可能,那么最终的可能性就是 $2^n$ 个,显然无法通过此题。但我们注意到其可能产生的 状态 ,即小鹿在某次动作开始时所站的位置,只有最多x种,因而我们可以尝试对每一次动作枚举其发生时可能的状态,这样复杂度就能够被控制在O( $n \cdot x$ )的级别了
具体而言,我们可以建立一个二维数组 $dp$ ,我们将 $dp[i][j]$ 定义为在第 $i$ 次操作后,能否到达第 $j$ 个格子。最初,我们将 $dp[0][0]$ 设为 $1$ (即未进行任何操作时,能够到达第0个格子),其余值设为 $0$ 。随后,对于第 $i$ 次操作,我们遍历上一次操作产生的 $dp[i-1]$ 数组,如果 $dp[i-1][j]$ 是 $1$ ,即上一次操作后能够到达第 $j$ 格,那么在本次操作中,第 $j+a_i$ 和 $j+b_i$ 这两个格子也是能够达到的(前提是这两个格子不大于 $x$ ),即 $dp[i][j+a_i],dp[i][j+b_i]$ 均也为 $1$ 。依照此方法遍历完所有 $n$ 次操作后,我们只需要检查 $dp[n][x]$ 是否为 $1$ 即可。
这种做法基于动态规划(DP)的思想,如果你自己悟出了此题的解法,大概有日后成为队里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
#include<bits/stdc++.h>
using namespace std;
int main(){
int dp[110][10010];
int n,x;
cin>>n>>x;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
for(int j=a;j<=x;j++){
if(dp[i-1][j-a]){
dp[i][j]=1;
}
}
for(int j=b;j<=x;j++){
if(dp[i-1][j-b]){
dp[i][j]=1;
}
}
}
if(dp[n][x])cout<<"YES";
else cout<<"NO";
return 0;
}
DLC:热身赛题解
复刻早年入队赛经典了属于是
1
BBBBBBBBBBBB