当前位置:   article > 正文

蓝桥杯第十一届国赛题目B组C++_第十一届蓝桥杯b组c++

第十一届蓝桥杯b组c++

A 美丽的2

【问题描述】
小蓝特别喜欢2,今年是公元2020年,他特别高兴。
他很好奇,在公元1年到公元2020年(包含)中,有多少个年份的数位中包含数字2?

#include <iostream>
#include <cstdio>
using namespace std;
int main(){
	int sum=0,n=2020;
	for(int i=1;i<=n;i++){
		int year=i;
		while(year>0){
			if(year%10==2){
				sum++;
				break;
			}
			year/=10;
		}
	}
	printf("%d\n",sum);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
答案:563
  • 1

B:扩散

【问题描述】
小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。小蓝在画布上首先点了一下几个点:(0,0),(2020,11),(11,14),(2000,2000)。只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。
请问,经过2020分钟后,画布上有多少个格子是黑色的。

#include <iostream>
#include <cstdio>
using namespace std;
//(0,0),(2020,11),(11,14),(2000,2000)
int main() {
	long long sum = 0;
	for (int i = -5000; i <= 5000; i++) {
		for (int j = -5000; j <= 5000; j++) {
			if (((abs(i-0)+abs(j-0))<=2020)||((abs(i-2020)+abs(j-11))<=2020)||((abs(i-11)+abs(j-14))<=2020)||((abs(i-2000)+abs(j-2000))<=2020)) {
				sum++;
			}
		}
	}
	printf("%lld\n", sum);
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
答案: 20312088
  • 1

C阶层约数

【问题描述】
定义阶乘n!=1×2×3×··×n。
请问100! (100的阶乘)有多少个约数。
在这里插入图片描述
例如:10的质数乘积=25 ,约数个数=(1+1)(1+1)=4;如上所说1 2 5 10

180的质数乘积=2x2x3x3x5,约数个数=(2+1)(2+1)(1+1)=18。约数为
1 2 3 4 5 6 9 10 12 15 18 20 30 36 45 60 90 180 。
a1,a2,a3就是分解质因数出现的个数(幂数),180分解后=2^2 + 2^3 + 5^1。

#include <iostream>
#include <cstdio>
using namespace std;
int arr[105];

int main() {
	//记录结果
	long long sum=1;
	for (int i = 2; i <= 100; i++) {
		//将每个数分解质因数,即将这个数分为质数乘积组成的形式,记录分解的数出现次数。
		int j = 2, i1 = i;
		while (i1 != j) {
			if (i1 % j == 0) {
				arr[j]++;
				i1 = i1 / j;
			} else {
				j++;
			}
		}
		//最后i1==j就是分解到最后一个质数,将这个质数记录
		arr[j]++;
	}
	//根据公式,约数个数=(a1+1)*(a2+1)*(an+1)...a就是质因数出现次数(幂数)
	for (int i=2; i<=100; i++) {
		if (arr[i]!=0)
			sum*=(arr[i]+1);
	}
	//输出结果
	cout << sum << endl;
	return 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 <iostream>
using namespace std;
int p[100];
int main()
{
	for (int i = 2; i <= 100; i ++)
	{
		int n = i;
		for (int j = 2; j <= n / j; j ++)
			while(n % j == 0)
			{
				p[j] ++;
				n /= j;
			}
		if(n > 1) p[n] ++;	
	}
	
	long long ans = 1;
	for (int i = 2; i <= 100; i ++)
		if(p[i]) ans *= (p[i] + 1);

	cout << ans << endl;
	return 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
答案:  39001250856960000
  • 1

D:本质上升序列

【问题描述】
小蓝特别喜欢单调递增的事物。
在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
例如,在字符串 lanqiao 中,如果取出字符n和 q,则nq组成一个单调递增子序列。类似的单调递增子序列还有lnq、 i、 ano 等等。
小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第二个字符和最后一个字符可以取到 ao,取最后两个字符也可以取到ao。小蓝认为他们并没有本质不同。
对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个?
例如,对于字符串 lanqiao,本质不同的递增子序列有21个。它们分别是l、a、n、q、 i、o、ln、an、lq、aq、nq、ai、lo、ao、no、io、lnq、anq、 lno、 ano、 aio。
请问对于以下字符串(共200个小写英文字母,分四行显示):(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 inc.txt,内容与下面的文本相同>
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkghfwl
本质不同的递增子序列有多少个?

在这里插入代码片
  • 1

E:玩具蛇

小蓝有一条玩具蛇,一共有16 节,上面标着数字1 至16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成90 度角。
小蓝还有一个4 X 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母A 到P 共16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。
下图给出了两种方案:
在这里插入图片描述
请帮小蓝计算一下,总共有多少种不同的方案。如果两个方案中,存在玩具蛇的某一节放在了盒子的不同格子里,则认为是不同的方案。

#include <iostream>
#include <cstring>
using namespace std;

int vis[7][7] = {0};
long long ans = 0;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void dfs(int x, int y, int step) {
	
	if (vis[x][y]==1) {
		return;
	}
	
	if (step == 16) {
		ans++;
		return;
	}
	
	vis[x][y] = 1;
	
	for (int it = 0; it < 4; it++) {
		if (vis[x + dx[it]][y + dy[it]] == 0 &&
			1 <= x + dx[it] && x + dx[it] <= 4 &&
			1 <= y + dy[it] && y + dy[it] <= 4) {
			dfs(x + dx[it], y + dy[it], step + 1);
		}
	}
	
	vis[x][y] = 0;
}
int main() {
	for (int i = 1; i <= 4; i++) {
		for (int j = 1; j <= 4; j++) {
			memset(vis, 0, sizeof(vis));
			dfs(i, j, 1);
		}
	}
	cout << ans;
	return 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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
答案: 552
  • 1

F: 皮亚诺曲线距离

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

G: 游园安排

在这里插入图片描述

在这里插入图片描述
链接: 原文地址
方法一:动态规划+回溯(70%)
在这里插入图片描述

//方法一:动态规划+回溯
#include <iostream>
#include <cstdio>

using namespace std;
const int N = 1e6+10;

int num;
string s;
int f[N];	//按照顺序存储
string v[N];//存储分割人名

int main() {
	string s;
	cin>>s;
	//s="WoAiLanQiaoBei";

	for (int i=0; i<s.length(); i++) { //分割字符串
		if (s[i]>='A'&&s[i]<='Z') {
			num++;
			v[num]="";
			v[num]+=s[i];
		} else {
			v[num]+=s[i];
		}
	}

	int max1=0;//最长字典长度(人名的个数)
	max1=0;//开始数组长度为空
	int pos=1;
	for (int i=1; i<=num; i++) {
		f[i]=1;
		for (int j=1; j<i; j++) { //查找后边的人名
			if (v[j]<v[i]) {
				f[i]=max(f[i], f[j]+1);
			}
		}
		if (f[i]>=max1) {
			max1=f[i];
			pos=i;
		}
	}

	string res="";
	for (int i=pos; i>=1; i--) {
		if (f[i]==max1) {
			res=v[i]+res;
			max1--;
		}
	}

	cout<<res<<endl;
	return 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
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

方法二:动态规划优化-二分加贪心(100%)
在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;

int num;
string s;
string v[N];
vector<string> endd;
vector<int> f;

int main()
{
	cin>>s;
	for(int i=0;i<s.length();i++)
	{
		if(s[i]>='A'&&s[i]<='Z')
		{
			if(i!=0)
				num++;
			v[num]="";
			v[num]+=s[i];
		}
		else
		{
			v[num]+=s[i];
		}
	}
	endd.push_back(v[0]);
	f.push_back(1);
	for(int i=1;i<=num;i++)	//遍历到最后一个子字符串数组元素 
	{
		if(v[i]>endd.back())	//如果当前end中的字符串能构成上升序列 
		{
			endd.push_back(v[i]);	//则将当前子字符串入队 
			f.push_back(endd.size());	//那么当前动态数组的长度就是当前上升序列的长度 
		}
		else 
		{   //下面是贪心做法 
			//如果不能构成单调上升序列
			int pos=lower_bound(endd.begin(),endd.end(),v[i])-endd.begin();	
			//找到大于等于序列v[i]的第一个元素的位置 
				 
			endd[pos]=v[i];	//将这个元素替换为v[i](这个可能不好理解,下面会说的) 
			f.push_back(pos+1);
			//更新一下,那么当前的上升序列的长度就是pos+1(因为0-pos是单调上升的,加上0这个首元素所以是pos+1) 
		}
	}
	string k[N];	//用字符串连接会超时 
  	int cnt=0;
	for(int i=num,m=endd.size();m>0;i--)	//类似动态规划将结果逆序输出
	 {
		if(f[i]==m)	
		{	
			k[cnt++]=v[i];
			m--;
		}
	}
  	for(int i=cnt-1;i>=0;i--) cout<<k[i];
	return 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
  • 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

H: 答疑

在这里插入图片描述
在这里插入图片描述

在这里插入代码片
  • 1

I: 出租车

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

J: 质数行者

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/440979
推荐阅读
相关标签
  

闽ICP备14008679号