第十一届蓝桥杯国赛C/C++B组题目及部分题解


真题链接:点这里

填空题

试题A:美丽的2(5分)

问题描述:

思路简述:

简单模拟

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
using namespace std;
int main(){
int n,ans=0;cin>>n;
for(int i=1;i<=n;++i){
int m=i;
while(m){
if(m%10==2)break;
m/=10;
}
if(m)ans++;
}
cout<<ans<<endl;
return 0;
}

参考结果:

563

试题B:既约分数(5分)

问题描述:

思路简述:

简单模拟

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
// 返回a和b的最大公约数
int main(){
int n=2020,ans=0;
for(int i=1;i<n;++i)
for(int j=i+1;j<=n;++j)
if(gcd(i,j)==1)ans+=2;
cout<<ans+1<<endl;
// 1/1也算哦
return 0;
}

参考结果:

2481215


试题C:蛇形填数(10分)

问题描述:

思路简述:

解法一:

第20行第20列位于斜着数第 20*2-1=39行,找到39行的首和尾两个数,进行计算742+(780-742)/2=761

代码:
1
2
3
4
5
6
7
8
9
10
#include<iostream>
using namespace std;
int main(){
int n=39,a=0,sum=0;
for(int i=1;i<=n;++i){
a++;sum+=a;cout<<sum<<endl;
}
cout<<endl<<(sum-a+1)+a/2<<endl;
return 0;
}

解法二:

简单模拟。用二维vectorv来存储这斜着数39行内容。

代码:
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<iostream>
#include<vector>
using namespace std;
int main(){
int n=39;
vector<vector<int>>v(n,vector<int>(n));
int x=0,y=0,num=0;
for(int i=0;i<n;++i){
for(int j=0;j<=i;++j){
v[x][y]=++num;
if(j==i){ //到这一斜行的右端点
if(i&1)++x;
else ++y;
}
else{
if(i&1)++x,--y;
else ++y,--x;
}
}
}
for(int i=0;i<n;++i){
for(int j=0;j<n-i;++j)cout<<v[i][j]<<" ";
cout<<endl;
}
cout<<endl<<v[19][19]<<endl;
return 0;
}

参考结果:

761


试题D:跑步锻炼(10分)

问题描述:

思路简述:

模拟题。用mon存储第i月的日数。

代码:

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<iostream>
#include<vector>
using namespace std;
int main(){
vector<int>mon{0,31,28,31,30,31,30,31,31,30,31,30,31};
int y=2020,m=10,d=1;
int ans=0,week=6;
// week 记录今天是星期几
for(int i=2000;i<=y;++i){ // i,j,k 枚举年月日
for(int j=1;j<=12;++j){
int end=mon[j];
if((i%400==0||i%4==0&&i%100!=0)&&j==2)end++;
// 闰年2月29天
for(int k=1;k<=end;++k){
ans++;
if(k==1||week==1)ans++;
week=week==7?1:week+1; // 若为星期日则转为星期一
if(i==y&&j==m&&k==d){
cout<<ans<<endl;return 0;
}
}
}
}
return 0;
}

参考结果:

8879


试题E:七段码(15分)

问题描述:

思路简述:

不会嗷



程序题

试题F:成绩统计(15分)

答题链接:点这里

问题描述:

  • 样例输入

    1
    2
    3
    4
    5
    6
    7
    8
    7
    80
    92
    56
    74
    88
    100
    0
  • 样例输出

    1
    2
    71%
    43%

思路简述:

简单模拟

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream> 
using namespace std;
int main(){
int n,score,pass=0,excellent=0;cin>>n;
for(int i=0;i<n;++i){
cin>>score;
if(score>=60)pass++;
if(score>=85)excellent++;
}
cout<<(int)(pass*100.0/n+0.5)<<"%"<<endl;
cout<<(int)(excellent*100.0/n+0.5)<<"%"<<endl;
return 0;
}

试题G:回文日期(20分)

答题链接:点这里

问题描述:

  • 样例输入

    1
    20200202
  • 样例输出

    1
    2
    20211202
    21211212

思路简述:

枚举当前日期~`99999999`

判断当前i是否符合日期规范

若日期有效,接着判断日期是否为回文串

若为回文串,接着判断是否为ababbaba型

代码:

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
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdlib>
using namespace std;
vector<int>mon{0,31,28,31,30,31,30,31,31,30,31,30,31};
bool isYear(int y){ // 判断是不是闰年
return y%4==0&&y%100!=0||y%400==0;
}
bool judgeDate(int y,int m,int d){ // 判断该日期是否有效
if(m>12)return 0; // 是月份>12不正确哦
if(isYear(y)&&m==2)return d<=29; // 闰年的二月份
return d<=mon[m];
}
int main(){
int n,f1=1,f2=1;cin>>n;
for(int i=n+1;i<=99999999;++i){
int y=i/10000; // 年
int m=i/100%100; // 月
int d=i%100; // 日
if(!judgeDate(y,m,d))continue;
if(!f1&&!f2)break; // 都找到啦
string a=to_string(i); // 转成字符串
string b=a;
reverse(b.begin(),b.end());
if(a==b){ // 回文字符串
if(f1){
cout<<i<<endl;f1=0;
}
// ababbaba型
if(a[0]==a[2]&&a[1]==a[3]&&a[1]!=a[2]&&f2){
cout<<i<<endl;f2=0;
}
}
}
return 0;
}

试题H:子串分值和(20分)

答题链接:点这里

问题描述:

  • 样例输入

    1
    ababc
  • 样例输出

    1
    28
  • 样例说明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    子串 f值
    a 1
    ab 2
    aba 2
    abab 2
    ababc 3
    b 1
    ba 2
    bab 2
    babc 3
    a 1
    ab 2
    abc 3
    b 1
    bc 2
    c 1

思路简述:

v来存储26个字母最后一次出现的位置

假设每个区间都是第一个出现的字母有贡献值,则贡献值为与左边相同字母的距离*右边字母个数

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
vector<int>v(26);
// 最后一次出现i+'a'的位置
int main(){
string s;cin>>s;
ll ans=0;
for(int i=0;i<26;++i)v[i]=-1; // 初始化
ll n=s.length();
for(int i=0;i<n;++i){
ans+=(i-v[s[i]-'a'])*(n-i);
v[s[i]-'a']=i;
}
cout<<ans<<endl;
return 0;
}

试题I:平面切分(25分)

答题链接:点这里

问题描述:

  • 样例输入

    1
    2
    3
    4
    3
    1 1
    2 2
    3 3
  • 样例输出

    1
    6

思路简述:

  • 只能过部分样例,一个小想法,但是用AcWing 提交wrong answer了

先用set去点重复的点,接着遍历每个点,计算每个点与前几个点的斜率A和截距B ,计算不重复的{A,B}对个数,当前点与前几个点将平面分为个数+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
#include<iostream>
#include<set>
using namespace std;
set<pair<double,double>>p;
//用set储存每条边(不重复)
double a[1001],b[1001];
int main(){
int n,ans=2,cnt=0;cin>>n;
double x,y;
for(int i=0;i<n;++i){
cin>>x>>y;p.insert({x,y});
}
n=p.size();
set<pair<double,double>>::iterator it;
for(it=p.begin();it!=p.end();++it)
a[cnt]=it->first,b[cnt++]=it->second;
for(int i=1;i<n;++i){
set<pair<double,double>>st;
//储存第i条线与之前的交点坐标
for(int j=i-1;j>=0;--j){
if(a[i]==a[j])continue;
x=(b[j]-b[i])/(a[i]-a[j]); //交点的x坐标
y=a[i]*x+b[i]; //交点的y坐标
st.insert({x,y});
}
ans+=st.size()+1;
}
cout<<ans<<endl;
return 0;
}

试题J:字串排序(25分)

答题链接:点这里

问题描述:

  • 样例输入1

    1
    4
  • 样例输出1

    1
    bbaa
  • 样例输入2

    1
    100
  • 样例输出2

    1
    jihgfeeddccbbaa

思路简述:

不会嗷



文章作者: Wsy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Wsy !
  目录