蓝桥杯第十二届国赛题目B组C++

试题 A: 带宽

【问题描述】
小蓝家的网络带宽是 200 Mbps,请问,使用小蓝家的网络理论上每秒钟最多可以从网上下载多少 MB 的内容。

200M带宽 实际网速每秒25M 带宽 除以 8 等于 每秒网速
答案 200/8 = 25

试题 B: 纯质数

【问题描述】
如果一个正整数只有 1 和它本身两个约数,则称为一个质数(又称素数)。

前几个质数是: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 中,有多少个纯质数?

#include <iostream>
#include <cstdio>
#include<cstring>
using namespace std;
int sum=0;
int noprime[30000000];
int m=20210605;

void check() {
	
	memset(noprime, 0, sizeof(noprime));
	noprime[2]=0;
	noprime[1]=1;
	noprime[0]=1;
	for (int i=2; i<=m; i++) {
		if (!noprime[i]) {
			for (int j=i*2; j<=m; j+=i) {
				noprime[j]=1;
			}
		}
	}
}

int fun(int i) {
	if (noprime[i])
		return 0;

	if (!noprime[i]) {
		int t=i;
		while (t) {
			if (noprime[t%10]) {
				return 0;
			}
			t/=10;
		}
	}
	return 1;
}
int main() {
	check();
	for (int i=0; i<=m; i++) {
		sum+=fun(i);
	}
	cout<<sum<<endl;
	return 0;
}
#include <bits/stdc++.h>

using namespace std;
#define ENDL "\n"
typedef long long ll;
typedef pair<int, int> pii;
const int Mod = 1e9 + 7;
const int maxn = 3e7 + 10;

vector<int> prime;
bitset<maxn> vis;

void euler() {
    vis.set();
    vis[0] = 0;
    vis[1] = 0;
    for (int i = 2; i < maxn; i++) {
        if (vis[i]) prime.push_back(i);
        for (int j = 0; j < prime.size() && i * prime[j] < maxn; j++) {
            vis[i * prime[j]] = 0;
            if (i % prime[j] == 0) break;
        }
    }
}

bool check(int x) {
    while (x) {
        if (!vis[x % 10]) return 0;
        x /= 10;
    }
    return 1;
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int ans = 0;
    euler();
    for (int i = 1; i <= 20210605; i++) {
        if (vis[i] && check(i)) ans++;
    }
    cout << ans << ENDL;
    return 0;
}

答案: 1903

试题 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 日中,一共有多少个完全日期?

#include <iostream>
#include <cstdio>

using namespace std;
int ren[]= {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int ping[]= {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int a[]= {0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100};

bool isRen(int y) {
	if ((y%4==0&&y%100!=0)||y%400==0)
		return true;
	return false;
}

int getValue(int n) {
	int t=0;
	while (n) {
		t+=n%10;
		n/=10;
	}
	return t;
}

int check(int y, int m, int d) {
	int s=getValue(y)+getValue(m)+getValue(d);
	for (int i=1; i<=9; i++) {
		if (s==a[i])
			return 1;
	}
	return 0;
}

int main() {
	int ans=0;
	for (int y=2001; y<=2021; y++) {
		for (int m=1; m<=12; m++) {
			if (isRen(y)) {
				for (int d=1; d<=ren[m]; d++) {
					ans+=check(y, m, d);
				}
			} else {
				for (int d=1; d<=ping[m]; d++) {
					ans+=check(y, m, d);
				}
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
答案: 977

试题 D: 最小权值

【问题描述】
对于一棵有根二叉树 T ,小蓝定义这棵树中结点的权值 W(T ) 如下:
空子树的权值为 0。
如果一个结点 v 有左子树 L, 右子树 R,分别有 C(L) 和 C(R)个结点,则
W(v) = 1 + 2W(L) + 3W(R) + (C(L))^2 C(R)。
树的权值定义为树的根结点的权值。
小蓝想知道,对于一棵有 2021 个结点的二叉树,树的权值最小可能是多少?

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
long long f[2022];

int main(){
	memset(f,127,sizeof(f));
	f[0]=0;
	for(int i=1;i<=2021;i++){
		for(int j=0;j<i;j++){
			f[i]=min(f[i],1+2*f[j]+3*f[i-1-j]+j*j*(i-1-j));
		}
	}
	cout<<f[2021]<<endl;
	return 0;
}
答案: 2653631372

试题 E: 大写

【问题描述】
给定一个只包含大写字母和小写字母的字符串,请将其中所有的小写字母转换成大写字母后将字符串输出。

【输入格式】

输入一行包含一个字符串。

【输出格式】

输出转换成大写后的字符串。

【样例输入 1】

LanQiao

【样例输出 1】

LANQIAO

#include<bits/stdc++.h>
#include<iostream>
#define ll long long
using namespace std;

int main(){
	string str;
	cin >> str;
	for(int i = 0; i < str.length(); i++){
		if(str[i] >= 'a' && str[i] <= 'z'){
			str[i] -= ('a'-'A'); 
		}
	}
    cout << str;
	return 0;
} 

试题 F: 123

【问题描述】
小蓝发现了一个有趣的数列,这个数列的前几项如下:
1, 1, 2, 1, 2, 3, 1, 2, 3, 4, …
小蓝发现,这个数列前 1 项是整数 1,接下来 2 项是整数 1 至 2,接下来
3 项是整数 1 至 3,接下来 4 项是整数 1 至 4,依次类推。小蓝想知道,这个数列中,连续一段的和是多少。

【输入格式】

输入的第一行包含一个整数 _T _,表示询问的个数。
接下来 _T _行,每行包含一组询问,其中第 _i _行包含两个整数 _li _和 ri,表示询问数列中第 _li _个数到第 _ri _个数的和。

【输出格式】

输出 _T _行,每行包含一个整数表示对应询问的答案。

【样例输入】

3
1 1
1 3
5 8

【样例输出】

1
4
8

【评测用例规模与约定】

对于 10% 的评测用例,1 ≤ _T _≤ 30, 1 ≤ _li _≤ _ri _≤ 100。 对于 20% 的评测用例,1 ≤ _T _≤ 100, 1 ≤ _li _≤ _ri _≤ 1000。对于 40% 的评测用例,1 ≤ _T _≤ 1000, 1 ≤ _li _≤ _ri _≤ 106。对于 70% 的评测用例,1 ≤ _T _≤ 10000, 1 ≤ _li _≤ _ri _≤ 109。对于 80% 的评测用例,1 ≤ _T _≤ 1000, 1 ≤ _li _≤ _ri _≤ 1012。
对于 90% 的评测用例,1 ≤ _T _≤ 10000, 1 ≤ _li _≤ _ri _≤ 1012。对于所有评测用例,1 ≤ _T _≤ 100000, 1 ≤ _li _≤ _ri _≤ 1012。
在这里插入图片描述

#include <iostream>
#include <cstdio>

using namespace std;
typedef long long LL;

//(1) (1,2) (1,2,3) (1,2,3,4)  …… 
LL cal1(LL n) {//前n个单元和
	return n*(n+1)*(n+2)/6;
}

//前n个单元数字总个数
LL cal2(LL n) {
	return n*(n+1)/2;
}

//获得单元数
LL getSeg(LL n) {
	LL l=1, r=1e9, mid, ans;
	while (l<=r) {
		mid=(l+r)>>1;
		if (cal2(mid)<=n) {
			ans=mid;
			l=mid+1;
		} else {
			r=mid-1;
		}
	}
	return ans;
}

LL solve(LL n) {
	if (n==0)
		return 0;
	LL s=getSeg(n);
	return cal2(n-cal2(s))+cal1(s);
}
int main() {
	int T;
	LL l, r;
	scanf("%d", &T);
	while (T--) {
		scanf("%lld%lld", &l, &r);
		printf("%lld\n", solve(r)-solve(l-1));
	}
	return 0;
}

试题 G: 异或变换

【问题描述】
小蓝有一个 01 串 s = s1 s2 s3 · · · sn。
以后每个时刻,小蓝要对这个 01 串进行一次变换。每次变换的规则相同。对于 01 串 s = s1 s2 s3 · · · sn,变换后的 01 串 s′ = s′1 s′2 s′3 · · · s′n 为:
s′1 = s1;
s′i = si−1 ⊕ si 。
其中 a ⊕ b 表示两个二进制的异或,当 a 和 b 相同时结果为 0,当 a 和 b不同时结果为 1。
请问,经过 t 次变换后的 01 串是什么?

【输入格式】

输入的第一行包含两个整数 n, t,分别表示 01 串的长度和变换的次数。第二行包含一个长度为 n 的 01 串。

【输出格式】

输出一行包含一个 01 串,为变换后的串。

【样例输入】

5 3

10110

【样例输出】

11010

【样例说明】

初始时为 10110,变换 1 次后变为 11101,变换 2 次后变为 10011,变换 3次后变为 11010。

【评测用例规模与约定】

对于 40% 的评测用例,1 ≤ n ≤ 100, 1 ≤ t ≤ 1000。
对于 80% 的评测用例,1 ≤ n ≤ 1000, 1 ≤ t ≤ 109。
对于所有评测用例,1 ≤ n ≤ 10000, 1 ≤ t ≤ 1018。

#include <iostream>
#include <cstdio>

using namespace std;
const int N = 1e4+5;
int n, a[N], b[N];
long long t;
char str[N];
int main() {

	scanf("%d%lld%s", &n, &t, &str);
	t%=16384;//循环16384次之后恢复原状
	for (int i=1; i<=n; i++) {
		if (str[i-1]=='0')
			a[i]=0;
		else
			a[i]=1;
	}
	for (int i=1; i<=t; i++) {
		for (int j=1; j<=n; j++) {
			b[j]=a[j-1]^a[j];
		}
		memcpy(a, b, sizeof(a));
	}
	for (int i=1; i<=n; i++) {
		if (a[i]) {
			printf("1");
		} else {
			printf("0");
		}
	}
	printf("\n");
	return 0;
}

试题 H: 二进制问题

【问题描述】
小蓝最近在学习二进制。他想知道 1 到 N 中有多少个数满足其二进制表示中恰好有 K 个 1。你能帮助他吗?

【输入格式】

输入一行包含两个整数 N 和 K。

【输出格式】

输出一个整数表示答案。

【样例输入】

7 2

【样例输出】

3

【评测用例规模与约定】

对于 30% 的评测用例,1 ≤ N ≤ 106, 1 ≤ K ≤ 10。
对于 60% 的评测用例,1 ≤ N ≤ 2 × 109, 1 ≤ K ≤ 30。对于所有评测用例,1 ≤ N ≤ 1018, 1 ≤ K ≤ 50。

在这里插入代码片

试题 I: 翻转括号序列

【问题描述】
给定一个长度为 _n _的括号序列,要求支持两种操作:

将 [Li, Ri] 区间内(序列中的第 Li 个字符到第 Ri 个字符)的括号全部翻转(左括号变成右括号,右括号变成左括号)。
求出以 _Li _为左端点时,最长的合法括号序列对应的 _Ri _(即找出最大的
Ri 使 [Li, Ri] 是一个合法括号序列)。

【输入格式】

输入的第一行包含两个整数 n, m,分别表示括号序列长度和操作次数。第二行包含给定的括号序列,括号序列中只包含左括号和右括号。
接下来 m 行,每行描述一个操作。如果该行为 “1 Li Ri”,表示第一种操作,区间为 [Li, Ri] ;如果该行为 “2 Li” 表示第二种操作,左端点为 Li。
【输出格式】
对于每个第二种操作,输出一行,表示对应的 Ri。如果不存在这样的 Ri,请输出 0。

【样例输入】

7 5
((())()
2 3
2 2
1 3 5
2 3
2 1

【样例输出】

4
7
0
0

【评测用例规模与约定】
对于 20% 的评测用例,n, _m _≤ 5000; 对于 40% 的评测用例,n, _m _≤ 30000;对于 60% 的评测用例,n, _m _≤ 100000;
对于所有评测用例,1 ≤ _n _≤ 106, 1 ≤ _m _≤ 2 × 105。

在这里插入代码片

试题 J: 异或三角

【问题描述】
给定 T 个数 n1, n2, · · · , nT ,对每个 ni 请求出有多少组 a, b, c 满足:

1 ≤ a, b, c ≤ ni;
a ⊕ b ⊕ c = 0,其中 ⊕ 表示二进制按位异或;
长度为 a, b, c 的三条边能组成一个三角形。

【输入格式】

输入的第一行包含一个整数 T 。
接下来 T 行每行一个整数,分别表示 n1, n2, · · · , nT 。

【输出格式】

输出 T 行,每行包含一个整数,表示对应的答案。

【样例输入】

2

6

114514

【样例输出】

6

11223848130

【评测用例规模与约定】

对于 10% 的评测用例,T = 1, 1 ≤ ni ≤ 200;
对于 20% 的评测用例,T = 1, 1 ≤ ni ≤ 2000;对于 50% 的评测用例,T = 1, 1 ≤ ni ≤ 220;
对于 60% 的评测用例,1 ≤ T ≤ 100000, 1 ≤ ni ≤ 220;
对于所有评测用例,1 ≤ T ≤ 100000

在这里插入代码片
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值