2021第十二届蓝桥杯国赛B组【c/c++】
昨天刚刚打完国赛,坐着校车晃啊晃啊一路颠簸的…趁着今天脑子清醒了来一波。废话不多说,上题!
小白正在努力成长中,如有不对之处,敬请指正。
A 带宽
题目描述
小蓝家的网络带宽是 200 Mbps,请问,使用小蓝家的网络理论上每秒钟最多可以从网上下载多少 MB 的内容。
说明:这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只需要提交能输出正确答案的程序即可。
解题思路
bps指的是bit per second(比特每秒)。
B的英文全称为Byte(字节)。
换算关系:1 Byte = 8 bits。
故:200Mbps = 200/8 = 25 MB/s。
B 纯质数
题目描述
如果一个正整数只有 11和它本身两个约数,则称为一个质数(又称素数)。
前几个质数是:2,3,5,7,11,13,17,19,23,29,31,37,· · · 。
如果一个质数的所有十进制数位都是质数,我们称它为纯质数。
例如:2,3,5,7,23,37 都是纯质数,而11,13,17,19,29,31不是纯质数。当然 1,4,35也不是纯质数。
请问,在 1 到 20210605中,有多少个纯质数。
解题思路
暴力出结果!答案:1903
先判断出质数,在判断每个数位是否是质数,是就保留,不是丢弃。
上代码!
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector<long long>s;
void check(long long k)
{
int a=1,b,c,d=1;
for(long long i=2;i<=sqrt(k);i++)
{
if(k%i==0)
{
a=0;
break;
}
}
if(a==1)
{
b=k;
while(b>0)
{
c=b%10;
if(c!=2&&c!=3&&c!=5&&c!=7)
{
d=0;
break;
}
b=b/10;
}
if(d==1)
{
//cout<<k<<endl;
s.push_back(k);
}
}
}
int main()
{
for(long long i=1;i<=20210605;i++)
{
check(i);
}
cout<<s.size();
return 0;
}
(时间可能稍微有点久)
C 完全日期
题目描述
如果一个日期中年月日的各位数字之和是完全平方数,则称为一个完全日期。
例如:2021年6月5日的各位数字之和为2+0+2+1+6+5=16,而16是一个完全平方数,它是4的平方。所以2021年6月5日是一个完全日期。例如:2021年6月23日的各位数字之和为2+0+2+1+6+2+3=16,是一个完全平方数。所以2021年6月23日也是一个完全日期。
请问,从2001年1月1日到2021年12月31日中,一共有多少个完全日期?
解题思路
暴力出结果!答案:977
先判断年份是否是闰年,在依次遍历月份和日期,判断各位数字之和是否是完全平方数。
上代码!
#include <iostream>
#include <math.h>
using namespace std;
bool judge(long long k)
{
double t;
t=sqrt(((double)k));
if(((t*t))==((double)k))
{
return true;
}
return false;
}
int main()
{
long long b[21]={3,4,5,6,7,8,9,10,11,3,4,5,6,7,8,9,10,11,12,4,5};//年
long long d[12]={1,2,3,4,5,6,7,8,9,1,2,3};//月
long long c[31]={1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,3,4};//日
long long a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
long long i,j,k;
long long sum,count=0;
for(i=2001;i<=2021;i++)
{
sum=0;
if((i%4==0&&i%100!=0)||i%400==0)
{
a[1]=29;
}
sum=sum+b[i-2001];
for(j=0;j<12;j++)
{
sum=sum+d[j];
for(k=0;k<a[j];k++)
{
if(judge(sum+c[k]))
{
count++;
}
}
sum=sum-d[j];
}
a[1]=28;
}
cout<<count;
return 0;
}
D 最小权值
题目描述
对于一棵有根二叉树 T,小蓝定义这棵树中结点的权值 W(T)如下:
空子树的权值为 0。
如果一个结点 v 有左子树 L, 右子树 R,分别有 C(L)和 C®个结点,则 W(v) = 1 + 2W(L) + 3W® + (C(L))^2 C®。
树的权值定义为树的根结点的权值。
小蓝想知道,对于一棵有 2021个结点的二叉树,树的权值最小可能是多少。
解题思路
太难了,还在努力中。
记得比赛时萌生过一个很天真的想法,当没有右子树时,那么W(v) = 1 + 2W(L) + 3W® + (C(L))^2 C®可以演变为W(v) = 1 + 2W(L),那么无限寻找下去2021个结点的最小权值可能是2021哈哈哈哈哈。这仅仅是个天真的想法,好啦,等我翻书再看看先吧。
E 大写
题目描述
给定一个只包含大写字母和小写字母的字符串,请将其中所有的小写字母转换成大写字母后将字符串输出。
输入格式
输入一行包含一个字符串。
输出格式
输出转换成大写后的字符串。
样例
输入#1
LanQiao
输出#1
LanQiao
说明/提示
对于所有评测用例,字符串的长度不超过 100。
解题思路
上代码!
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cin>>s;
for(int i=0;i<s.size();i++)
{
if(s[i]>=97&&s[i]<=122)
{
s[i]=s[i]-32;
}
}
cout<<s;
return 0;
}
F 123
题目描述
小蓝发现了一个有趣的数列,这个数列的前几项如下:
1, 1, 2, 1, 2, 3, 1, 2, 3, 4, …
小蓝发现,这个数列前 11项是整数 1,接下来 2 项是整数 1 至 2,接下来 3 项是整数 1 至 3,接下来 4项是整数 1 至 4,依次类推。
小蓝想知道,这个数列中,连续一段的和是多少。
输入格式
输出格式
输出 T 行,每行包含一个整数表示对应询问的答案。
样例
输入#1
3
1 1
1 3
5 8
输出#1
1
4
8
说明/提示
解题思路
先说明该代码仅仅能通过了70%的样例,害!超时了,哭泣。
还在努力突破中。。。
想法是这样的,先判断起始数字位置和末尾数字的位置属于第几项。
这里用到了等差数列求和的计算公式。
判断出项位,就可以从第 i 项到第 j 项求和了。
上代码!
#include <iostream>
#include <math.h>
using namespace std;
struct A
{
long long l;
long long r;
};
long long judge(long long k)
{//判断属于第几项
long long t;
t=sqrt(k);
while((t*t+t)/2<k)
{
t++;
}
return t;
}
long long check(long long x,long long y)
{
long long sum=0;
long long n1,n2;
long long a,b;
n1=judge(x);//首项和尾项
n2=judge(y);
a=x-((n1-1)*(n1-1)+(n1-1))/2;
b=y-((n2-1)*(n2-1)+(n2-1))/2;
//计算首尾项的和
if(n1==n2)
{//如果首项和尾项属于同一项内,用等差数列求和公式计算
sum=sum+(b*b+b)/2-((a-1)*(a-1)+(a-1))/2;
}
else
{
sum=sum+(n1*n1+n1)/2-((a-1)*(a-1)+(a-1))/2;
sum=sum+(b*b+b)/2;
}
for(long long i=n1+1;i<n2;i++)
{//从首项后的第二项开始计算
sum=sum+(i*i+i)/2;
}
return sum;
}
int main()
{
long long t;
cin>>t;
A a[t];
for(long long i=0;i<t;i++)
{
cin>>a[i].l>>a[i].r;
}
for(long long i=0;i<t;i++)
{
cout<<check(a[i].l,a[i].r)<<endl;
}
return 0;
}
G 异或变换
题目描述
输入格式
输入的第一行包含两个整数 n, t,分别表示 01 串的长度和变换的次数。
第二行包含一个长度为 nn的 01 串。
输出格式
输出一行包含一个 01 串,为变换后的串。
样例
输入#1
5 3
10110
输出#1
11010
说明/提示
解题思路
先说明该代码仅仅能通过了60%的样例,害!我努力了还是超时了。。。
没啥思路,就一位一位的异或就好。
估计就是没有优化所以宕机了。。。
上代码!
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
long long n,t;
cin>>n>>t;
char s[10000],a[10000];
cin>>s;
for(long long i=0;i<t;i++)
{
a[0]=s[0];
for(long long j=1;j<n;j++)
{
if((s[j]^s[j-1])==0)
{
a[j]='0';
}
else
{
a[j]='1';
}
}
strcpy(s,a);
}
cout<<s;
return 0;
}
H 二进制问题
题目描述
小蓝最近在学习二进制。他想知道 1 到 N 中有多少个数满足其二进制表示中恰好有 K个 1。你能帮助他吗?
输入格式
输入一行包含两个整数 N 和 K。
输出格式
输出一个整数表示答案。
样例
输入#1
7 2
输出#1
3
说明/提示
解题思路
这题我只会暴力求解,所以还是超时了,好像只能通过30%的样例,见笑了。
有过一个可爱的想法:用排列组合问题, 对于1 到 N 个数,先找出二进制表示所需的最大位数,记为T,则相当于从T个位置中选择K个位置放1。
好了,这个可爱想法还未实现,没有代码。
只有暴力求解代码:
#include <iostream>
#include <math.h>
using namespace std;
long long check(long long x,long long y)
{
long long k;
long long count=0;
while(x>0)
{
k=x%2;
if(k==1)
{
count++;
if(count>y)
{
return 0;
}
}
x=x/2;
}
if(count==y)
{
return 1;
}
else{
return 0;
}
}
int main()
{
long long n,k;
long long sum=0;
cin>>n>>k;
for(long long i=1;i<=n;i++)
{
sum=sum+check(i,k);
}
cout<<sum;
return 0;
}
I 翻转括号序列
题目描述
输入格式
输出格式
样例
输入#1
7 5
((())()
2 3
2 2
1 3 5
2 3
2 1
输出#1
4
7
0
0
说明/提示
解题思路
没有思路。。。
J 异或三角
题目描述
输入格式
输出格式
样例
输入#1
2
6
114514
输出#1
6
11223848130
说明/提示
解题思路
依旧没有思路。。。
OK!以上就是小白第一次蓝桥国赛冒险的全部了,还有很多需要努力的地方,我会继续加油的!