第十一届蓝桥杯c++B组国赛

省赛传送门第十一届蓝桥杯省赛第二场

昨天在本校机房考的c++B组国赛,第十一届蓝桥杯因为疫情,原本在大二下学期考的,结果推迟到了大三上,想白嫖北京旅游也是泡汤了(hh,学校挺好,都报销了)。蒻蒻第一次参加,水了个国三。大概二个填空,一道大题,在顺便骗点分吧(hh),国三中。同学比我多做了个大题(游园安排)国三上。害,菜是本质。

不知道是第一次参加的缘故还是紧张,赛后又去看了下题目。填空最后一道考试的时候没读懂题意,考完读懂了,就一个简单的搜索。约数那题也是无语,不知道那个定理,知道了就很好写,可惜考场上递推式2^99,事实上只有一部分满足该规律。填空第二道扩散好在改改改对了,一开始就考虑了负数坐标,用的map瞎搞搞了半天。大题游园安排最长上升子序列当时也试了,没弄出来。最后一道大题,也是一个搜索。浪费太多时间了。最后没时间写了。题目放出来,待更----(写对的不想再写了,有空去机房拷回来放上)

#include<bits/stdc++.h>

using namespace  std;
const int N=1e5+5;
bool fun(int n)
{
	while(n){
		int t=n%10;
		if(t==2)return true;
		n/=10;
	}
	return false;
}
int main()
{
	int n,res=0;
	for(int i=1;i<=2020;i++){
		if(fun(i)){
			cout<<i<<'\n';
			res++;
		}
	}
	cout<<res<<'\n';	
	return 0;
}
//563


考试的时候写的,傻了,没想到简单算法。

#include<bits/stdc++.h>

using namespace std;
const int N=2e6+5;
int dir[4][2]={0,1,1,0,0,-1,-1,0},cnt=0;

map<pair<int,int>, int>vis;
struct node{
	int x,y,w;
}e[N];
typedef long long ll;
ll res=4;
void init()
{
	e[cnt].x=0;
	e[cnt].y=0;
	e[cnt].w=1;
	cnt++;
	e[cnt].x=2020;
	e[cnt].y=11;
	e[cnt].w=1;
	cnt++;
	e[cnt].x=11;
	e[cnt].y=14;
	e[cnt].w=1;
	cnt++;
	e[cnt].x=2000;
	e[cnt].y=2000;
	e[cnt].w=1;
	cnt++;
}
void count()
{
	//cout<<cnt<<'\n';
	for(int i=0;i<cnt;i++){
		if(e[i].w==1){
			res++;
			cout<<e[i].x<<' '<<e[i].y<<' '<<e[i].w<<'\n';
		}
	}
}
void bfs()
{
	int fen=0;
	queue<node>q1,q2;
	q1.push(e[0]);
	q1.push(e[1]);
	q1.push(e[2]);
	q1.push(e[3]);
	//vis[0][0]=1;vis[2020][11]=1;vis[11][14]=1;vis[2000][2000]=1;
//	cout<<q1.size()<<'\n';
//	node t=q1.front();
//	cout<<t.x<<' '<<t.y<<' '<<t.w<<'\n';
	while(1){
		fen++;
		//cout<<fen<<'\n';
		if(fen%2==1){
			while(q1.size()){
				node h=q1.front();
				q1.pop();
				for(int i=0;i<4;i++){
					node tt;
					tt.x=h.x+dir[i][0];
					tt.y=h.y+dir[i][1];
					tt.w=1;
					if(!vis[make_pair(tt.x,tt.y)]){
						q2.push(tt);
						vis[make_pair(tt.x,tt.y)]=1;
						res++;
					}
				}
			}
			while(q1.size())q1.pop();
		}else{
			while(q2.size()){
				node h=q2.front();
				q2.pop();
				for(int i=0;i<4;i++){
					node tt;
					tt.x=h.x+dir[i][0];
					tt.y=h.y+dir[i][1];
					tt.w=1;
					if(!vis[make_pair(tt.x,tt.y)]){
						q1.push(tt);
						vis[make_pair(tt.x,tt.y)]=1;
						res++;
					}
				}
			}
			while(q2.size())q2.pop();
		}
		if(fen==2020)break;
		//cout<<q1.size()<<' '<<q2.size()<<'\n';
	}
//	int cnt=0;
//	while(q2.size()){
//		node t=q2.front();
//		q2.pop();
//		cnt++;
//	}
//	cout<<cnt<<'\n';
	cout<<res<<'\n';
}
int main()
{
	init();
	vis.insert({make_pair(0,0),1});
	vis.insert({make_pair(2020,11),1});
	vis.insert({make_pair(11,14),1});
	vis.insert({make_pair(2000,2000),1});
	bfs();
	
	//cout<<res<<'\n';
	return 0;
}
//1000-6033980
//2020-20312088

C阶层约数

【问题描述】
定义阶乘 n! = 1 × 2 × 3 × · · · × n。
请问 100! (100 的阶乘)有多少个约数。

#include<bits/stdc++.h>

using namespace std;
const int N=1e5+5;
typedef long long ll;
ll res=1;
int vis[N];
map<int,int>mp;
void prime_()
{
	int n=100;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			for(int j=2*i;j<=n;j+=i)
			vis[j]=1;
		}
	}
}
void fun(int x)
{
	if(!vis[x]){
		mp[x]++;
	}else{
		for(int i=2;i<=x;i++){
			while(x%i==0){
				mp[i]++;
				x/=i;
			}
		}
		
	}
}
int main()
{
	 int n;
	 cin>>n;
	 prime_();
	 for(int i=2;i<=n;i++){
	 	fun(i);
	 }
	 for(auto x:mp){
//	 	cout<<x.first<<' '<<x.second<<'\n';
		res*=1ll*(x.second+1);
	 }
	 cout<<res<<'\n';
	return 0;
}
//39001250856960000

E: 玩具蛇

【问题描述】
小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成 90 度角。
小蓝还有一个 4 × 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母 A 到 P 共 16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。
下图给出了两种方案:

请帮小蓝计算一下,总共有多少种不同的方案,如果两个方案中,卒年在玩具蛇的某一节放在盒子的不同格子里,则认为是不同的方案数。
思路:枚举每个点,然后求路径方案。

#include<bits/stdc++.h>

using namespace std;
const int N=1e3+5;
int e[20][20],dir[4][2]={0,1,1,0,0,-1,-1,0};
int vis[20][20],res;
void dfs(int x,int y,int step)
{
	if(step==16){
		res++;
		return;
	}
	
	for(int i=0;i<4;i++){
		int xx=x+dir[i][0];
		int yy=y+dir[i][1];
		if(xx>=1&&xx<=4&&yy>=1&&yy<=4&&!vis[xx][yy]){
			vis[xx][yy]=1;
			dfs(xx,yy,step+1);
			vis[xx][yy]=0;
		}
	}
}
int main()
{
	for(int i=1;i<=4;i++){
		for(int j=1;j<=4;j++){
			vis[i][j]=1;
			dfs(i,j,1);
			vis[i][j]=0;
		}
	}
	cout<<res<<'\n';
  return 0;
}


答案:552

G: 游园安排

【问题描述】
L 星球游乐园非常有趣,吸引着各个星球的游客前来游玩。小蓝是 L 星球
游乐园的管理员。
为了更好的管理游乐园,游乐园要求所有的游客提前预约,小蓝能看到系
统上所有预约游客的名字。每个游客的名字由一个大写英文字母开始,后面跟
0 个或多个小写英文字母。游客可能重名。
小蓝特别喜欢递增的事物。今天,他决定在所有预约的游客中,选择一部
分游客在上午游玩,其他的游客都在下午游玩,在上午游玩的游客要求按照预
约的顺序排列后,名字是单调递增的,即排在前面的名字严格小于排在后面的
名字。
一个名字 A 小于另一个名字 B 是指:存在一个整数 i,使得 A 的前 i 个字
母与 B 的前 i 个字母相同,且 A 的第 i+1 个字母小于 B 的第 i+1 个字母。(如
果 A 不存在第 i + 1 个字母且 B 存在第 i + 1 个字母,也视为 A 的第 i + 1 个字
母小于 B 的第 i + 1 个字母)
作为小蓝的助手,你要按照小蓝的想法安排游客,同时你又希望上午有尽
量多的游客游玩,请告诉小蓝让哪些游客上午游玩。如果方案有多种,请输出
上午游玩的第一个游客名字最小的方案。如果此时还有多种方案,请输出第一
个游客名字最小的前提下第二个游客名字最小的方案。如果仍然有多种,依此
类推选择第三个、第四个……游客名字最小的方案。
【输入格式】
输入包含一个字符串,按预约的顺序给出所有游客的名字,相邻的游客名
字之间没有字符分隔。
【输出格式】
按预约顺序输出上午游玩的游客名单,中间不加任何分隔字符。
【样例输入】
WoAiLanQiaoBei
【样例输出】
AiLanQiao
【评测用例规模与约定】
对于 20% 的评测数据,输入的总长度不超过 20 个字母。
对于 50% 的评测数据,输入的总长度不超过 300 个字母。
对于 70% 的评测数据,输入的总长度不超过 10000 个字母。
对于所有评测数据,每个名字的长度不超过 10 个字母,输入的总长度不超
过 1000000 个字母。

思路:最长上升子序列

#include<bits/stdc++.h>

using namespace std;
const int N=5e4+5;
string e[N];
int cot;
int f[N],path[N];
void dfs(int cur)
{
	if(cur==0){
		return;
	}
	dfs(path[cur]);
	cout<<e[cur];
}
int main()
{
	string s,t;
	int cnt=0;
	cin>>s;
	for(int i=0;i<s.size();i++){
		if(s[i]>='A'&&s[i]<='Z'){
			if(cnt==0)
			t+=s[i];
			else{
				e[cot++]=t;
				t="";
				t+=s[i];
				cnt=0;
			}
			cnt++;
		}else{
			t+=s[i];
		}
		if(i==s.size()-1){
			e[cot++]=t;
		}
	}
	int maxx=-1,pos;
	for(int i=0;i<cot;i++){
		f[i]=1;
		for(int j=0;j<i;j++){
			if(e[j]<e[i]){
				f[i]=max(f[i],f[j]+1);
				path[i]=j;
				if(maxx<f[i]){
					maxx=f[i];
					pos=i;
				}
			}
		}
	}
	dfs(pos);
  return 0;
}
/*
WoAiLanQiaoBei
*/

J: 质数行者

【问题描述】
小蓝在玩一个叫质数行者的游戏。
游戏在一个 n×m×w 的立体方格图上进行,从北到南依次标号为第 1 行到
第 n 行,从西到东依次标号为第 1 列到第 m 列,从下到上依次标号为第 1 层到第 w 层。
小蓝要控制自己的角色从第 1 行第 1 列第 1 层移动到第 n 行第 m 列第 w层。每一步,他可以向东走质数格、向南走质数格或者向上走质数格。每走到一个位置,小蓝的角色要稍作停留。
在游戏中有两个陷阱,分别为第 r 1 行第 c 1 列第 h 1 层和第 r 2 行第 c 2 列第h2 层。这两个陷阱的位置可以跨过,但不能停留。也就是说,小蓝不能控制角色某一步正好走到陷阱上,但是某一步中间跨过了陷阱是允许的。
小蓝最近比较清闲,因此他想用不同的走法来完成这个游戏。所谓两个走法不同,是指小蓝稍作停留的位置集合不同。
请帮小蓝计算一下,他总共有多少种不同的走法。
提示:请注意内存限制,如果你的程序运行时超过内存限制将不得分。
【输入格式】
输入第一行包含两个整数 n, m, w,表示方格图的大小。
第二行包含 6 个整数,r 1 , c 1 , h 1 , r 2 , c 2 , h 2 ,表示陷阱的位置。
【输出格式】
输出一行,包含一个整数,表示走法的数量。答案可能非常大,请输出答
案除以 1000000007 的余数。
【样例输入】
5 6 1
3 4 1 1 2 1
【样例输出】
11
【样例说明】
用 (r,c,h) 表示第 r 行第 c 列第 h 层,可能的走法有以下几种:

扫描二维码关注公众号,回复: 12883526 查看本文章

1.(1,1,1) − (1,3,1) − (1,6,1) − (3,6,1) − (5,6,1)。
2.(1,1,1) − (1,3,1) − (3,3,1) − (3,6,1) − (5,6,1)。
3.(1,1,1) − (1,3,1) − (3,3,1) − (5,3,1) − (5,6,1)。
4.(1,1,1) − (3,1,1) − (3,3,1) − (3,6,1) − (5,6,1)。
5.(1,1,1) − (3,1,1) − (3,3,1) − (5,3,1) − (5,6,1)。
6.(1,1,1) − (3,1,1) − (5,1,1) − (5,3,1) − (5,6,1)。
7.(1,1,1) − (3,1,1) − (5,1,1) − (5,4,1) − (5,6,1)。
8.(1,1,1) − (1,4,1) − (1,6,1) − (3,6,1) − (5,6,1)。
9。(1,1,1) − (1,6,1) − (3,6,1) − (5,6,1)。
10.(1,1,1) − (3,1,1) − (3,6,1) − (5,6,1)。
11.(1,1,1) − (3,1,1) − (5,1,1) − (5,6,1)。
【评测用例规模与约定】
对于 30% 的评测用例 1 ≤ n,m,w ≤ 50。
对于 60% 的评测用例 1 ≤ n,m,w ≤ 300。
对于所有评测用例,1 ≤ n,m,w ≤ 1000,1 ≤ r 1 ,r 2 ≤ n, 1 ≤ c 1 ,c 2 ≤ m,
1 ≤ h 1 ,h 2 ≤ w,陷阱不在起点或终点,两个陷阱不同。
思路:纯模拟,考场上sb了,没想到爆搜能骗这么多分。

#include<bits/stdc++.h>

using namespace std;
const int N=3e2+5,mod=1e9+7;
int e[N][N][N],vis2[N][N][N];
int n,m,w,r1,c1,h1,r2,c2,h2,cot;
int prime[N],vis[N],res;
void prime_(int x)
{
	for(int i=2;i<=x;i++){
		if(!vis[i]){
			prime[cot++]=i;
			for(int j=2*i;j<=x;j+=i)
			vis[j]=1;
		}
	}
}
bool check(int x,int y,int h)
{
	if(x==r1&&y==c1&&h==h1)return false;
	if(x==r2&&y==c2&&h==h2)return false;
	return true;
}
void print_()//打印路径 
{
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	for(int k=1;k<=w;k++)
	if(vis2[i][j][k]==1)
	cout<<i<<','<<j<<','<<k<<'-';
	cout<<'\n';
}
void dfs(int x,int y,int h)
{
	if(x==n&&y==m&&h==w){
		res=(res+1)%mod;
		//print_();//打印路径 
		return ;
	}
	for(int i=0;i<cot;i++){
		if(x+prime[i]<=n&&check(x+prime[i],y,h)){
			vis2[x+prime[i]][y][h]=1;
			dfs(x+prime[i],y,h);
			vis2[x+prime[i]][y][h]=0;
		}
		if(y+prime[i]<=m&&check(x,y+prime[i],h)){
			vis2[x][y+prime[i]][h]=1;
			dfs(x,y+prime[i],h);
			vis2[x][y+prime[i]][h]=0;
		}
		if(h+prime[i]<=h&&check(x,y,h+prime[i])){
			vis2[x][y][h+prime[i]]=1;
			dfs(x,y,h+prime[i]);
			vis2[x][y][h+prime[i]]=0;
		}
	}
}

int main()
{
	cin>>n>>m>>w;
	cin>>r1>>c1>>h1>>r2>>c2>>h2;
	int maxx=max(max(n,m),w);
	prime_(maxx);
	vis2[1][1][1]=1;
	dfs(1,1,1);
	vis2[1][1][1]=0;
	cout<<res<<'\n';
  return 0;
}
/*
5 6 1
3 4 1 1 2 1
*/


猜你喜欢

转载自blog.csdn.net/qq_43566782/article/details/109710563
今日推荐