第十一届蓝桥杯模拟赛软件B组-C/C++(思路分析)

一、问题描述

1200000有多少个约数(只计算正约数)?

#include<iostream> 
using namespace std;
int main()
{
	int N=1200000;
	int cnt=0;
	for(int i=1;i<=N;i++)
		if(N%i==0)
			cnt++;
	cout<<cnt<<endl;
return 0;
}

//96

二、问题描述

在计算机存储中,15.125GB是多少MB?

#include<iostream> 
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	cout<<15.125*1024;
return 0;
}
//15488

三、问题描述 

一颗包含有2019个结点的树,最多包含多少个叶结点?

// 2018
还有一个版本是:
一颗包含有2019个结点的二叉树,最多包含多少个叶结点?
//1010

 四、问题描述 

在1至2019中,有多少个数的数位中包含数字9?

#include<iostream> 
#include<cstdio>
using namespace std;
int main()
{
	int cnt=0;
	for(int i=9;i<=2019;i++)
	{
		char s[4];
		sprintf(s,"%4d",i);
		for(int j=0;j<4;j++)
			if(s[j]=='9')
			{
				cnt++;
				break;
			} 
	}
	cout<<cnt;
return 0;
}

//544

五、问题描述 

在数组a[1],a[2],...,a[n]中,如果对于下标i,j,k满足0<i<j<k<n+1,且a[i]<a[j]<a[k],则称a[i],a[j],a[k]为一组递增三元组,a[j]为递增三元组的中心 。

给定一个数列,请问数列中有多少个元素可以是递增三元组的中心。

输入格式:
       输入得第一行包含一个整数n。
       第二行包含n个整数a[1],a[2],…,a[n],相邻得整数间用空格分隔,表示给定的数列。

输出格式:
       输出一行包含一个整数,表示答案。

样例输入:
5
1 2 5 3 5

样例输出:
2

样例说明:
       a[2]和a[4]可能是三元组的中心。

评测用例规模与约定:
       对于50%的评测用例,2<=n<100,0<=数列中的数<=1000.。
       对于所有评测用例,2<=n<=1000,0<=数列中的数<=10000。
 

/*
思路:清除数组中重复的元素,去掉第一个元素和最后一个元素,剩下的元素的个数就是答案。
可以利用set容器的特性:不能存放相同的元素
ps:我没参加竞赛,下面的代码没提交过 
*/
#include<iostream> 
#include<set>
using namespace std;
set<int> st;
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int a;
		cin>>a;
		st.insert(a);
	}
	set<int>::iterator it;
	int cnt=-2;
	for(it=st.begin();it!=st.end();it++)
		cnt++;
	cout<<cnt<<endl;
return 0;
}


 

六、问题描述 

一个正整数如果任何一个数位不大于右边相邻的位数,则称为一个数位递增的数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。给定正整数你,请问在整数1至n中有多少个数位递增的数?

输入格式:
       输入的第一行包含一个整数n。

输出格式:
       输出一行包含一个整数,表示答案。

样例输入:
30

样例输出:
26

评测用例规模与约定:
       对于40%的评测用例,1<=n<1000。

       对于80%的评测用例,1<=n<100000。
       对于所有评测用例,1<=n<1000000。

/*
思路:将数字存入一个数组中,看是不是递减的数组。 
ps:我没参加竞赛,下面的代码没提交过 
*/
#include<iostream> 
using namespace std;
int main()
{
	int n;
	cin>>n;
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		int a[10]; 
		int j=0;
		int num=i;
		while(num)
		{
			a[j++]=num%10;
			num/=10;
		}
		cnt++;
		for(int k=0;k<j-1;k++)
			if(a[k]-a[k+1]<0)//如果不是递减的数组 
			{
				cnt--;
				break;
			}
	}
	cout<<cnt<<endl;
return 0;
}


 

七、问题描述 

小明对类似于hello这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。

给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no

元音字母包括a,e,i,o,u,共五个,其他均为辅音字母。

输入格式:
       输入一行,包含一个单词,单词中只包含小写英文字母。

输出格式:
       输出答案,或者为yes,或者为no。

样例输入:
lanqiao

样例输出:
yes

样例输入:
word

样例输出:
no

评测用例规模与约定:
       对于所有的评测用例,单词中的字母个数不超过100。

/*
思路:
移动下标,先检查辅音,如果不是辅音就跳出循环,从这个位置开始在检查元音,一共检查四次。
有两种情况 
1.如果下标没有移动到字符串末尾,就说明no
2.如果检查不到四次,下标就移动到了字符串末尾,就说明no
 
将元音的ASCII值作为key,对应数组的值变为1,方便检查。 

ps:我没参加竞赛,下面的代码没提交过 
*/
#include<iostream> 
#include<string>
using namespace std;
int a[200]={0};
string s;
int f(){
	int cnt=1;
	int i=0; 
	for(i;i<s.length();i++)
		if(a[s[i]]) //是元音 
			break;
	if(i==s.length()) 
		return 0;
	for(;i<s.length();i++)
		if(!a[s[i]]) //是辅音 
			break;
	if(i==s.length()) 
		return 0;
	for(;i<s.length();i++)
		if(a[s[i]]) 
			break;
	if(i==s.length()) 
		return 0;
	for(;i<s.length();i++)
		if(!a[s[i]]) 
			break;
	if(i==s.length()) 
		return 1;
	return 0;
}
int main()
{
	a['a']=1;
	a['e']=1;
	a['i']=1;
	a['o']=1;
	a['u']=1;
	while(cin>>s)
	{
		if(f()) cout<<"yes"<<endl;
		else cout<<"no"<<endl;
	}
return 0;
}


 

八、问题描述 

小明想知道,满足以下条件的正整数序列的数量:
  1. 第一项为 n;
  2. 第二项不超过 n;
  3. 从第三项开始,每一项小于前两项的差的绝对值。
  请计算,对于给定的 n,有多少种满足条件的序列。
输入格式
  输入一行包含一个整数 n。
输出格式
  输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
样例输入
4
样例输出
7
样例说明
  以下是满足条件的序列:
  4 1
  4 1 1
  4 1 2
  4 2
  4 2 1
  4 3
  4 4
评测用例规模与约定
  对于 20% 的评测用例,1 <= n <= 5;
  对于 50% 的评测用例,1 <= n <= 10;
  对于 80% 的评测用例,1 <= n <= 100;
  对于所有评测用例,1 <= n <= 1000。
 

/*
思路:
直接模拟过程 
但是有一个问题,就是当n大于20的时候,需要递归的层数太多太多了,指数爆炸
本题数据n<1000,所以这种方法不可行,需要改进---记忆化搜索 
ps:我没参加竞赛,下面的代码没提交过 
*/
#include<iostream> 
#include<cmath>
using namespace std;
int ans=0;
int dfs(int a1,int a2){//a1表示前一个数,a2表示后一个数 
	int b=fabs(a1-a2);
	for(int i=1;i<b;i++)
	{
		ans++;
		dfs(a2,i);
	}
}
int main()
{
	int n;
	cin>>n;
	dfs(0,n); 
	//因为dfs少计算了nn的情况,所有要+1 
	cout<<(ans+1)%10000<<endl;
return 0;
}


 

记忆化搜索:

/*
思路: 
根据题意画树,可知:答案=dp[n][1]+dp[n][2]+...+dp[n][n] 
ps:我没参加竞赛,下面的代码没提交过 
*/
#include<iostream> 
#include<cmath>
using namespace std;
int dp[1005][1005]={0};//dp[i][j]:当第一个数是i,第二个数是j时,正整数序列的数量 
int dfs(int a1,int a2){//a1表示前一个数,a2表示后一个数 
	if(dp[a1][a2]>0)
		return dp[a1][a2];
	for(int i=1;i<fabs(a1-a2);i++)
		dp[a1][a2]+=dfs(a2,i);
	return (dp[a1][a2]+1)%10000;
}
int main()
{
	int n;
	cin>>n;			
	int ans=0;
	for(int i=1;i<=n;i++)
		ans=(ans+dfs(n,i))%10000;
	cout<<ans<<endl;
	return 0;
}


 

九、问题描述 

小明有一块空地,他将这块空地划分为n行m列的小块,每行和每列的长度都为1。小明选了其中的一席小块空地,种上了草,其他小块仍然保持是空地。这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,这四小块空地都将变为有草的小块。请告诉小明,k个月后空地上哪些地方有草。
输入格式:
       输入的第一行包含两个整数n,m。接下来n行,每行包含m个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为g,表示种了草。接下来包含一个整数k。

输出格式:
       输出n行,每行包含m个字母,表示k个月后空地的状态。如果为小数点,表示为空地,如果字为g,表示长了草。

样例输入:
4 5
. g . . .
. . . . .
. . g . .
. . . . .
2

样例输出:
gggg.
gggg.
ggggg
.ggg.

评测用例规模与约定:
       对于30%的评测用例,2<=n,m<=20。
       对于70%的评测用例,2<=n,m<100。
       对于所有评测用例,2<=n,m<=1000,1<=k<=1000。
 

/*
思路: 
时间复杂度O(n*m) ,时间肯定是能过的 
把草的位置记录进队列。
然后bfs:
	拿出队头,如果月份是0,说明这个草已经不能生长了。
	如果草能生长,就向四面生长,进队列。
算是bfs的模板题吧 
*/
#include<iostream>
#include<queue>
using namespace std;
const int N=1002;
int n,m;
char map[N][N];
struct node{
	int x,y;
	int month;
};
queue<node> q;
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
void print(){
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
			cout<<map[i][j];
		cout<<endl;
	}
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		string s;
		cin>>s;
		for(int j=0;j<m;j++)
			map[i][j]=s[j];
	}
	int month;
	cin>>month;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(map[i][j]=='g')
			{
				node t;
				t.month=month;
				t.x=i;
				t.y=j;
				q.push(t);
			}
	//bfs
	while(!q.empty())
	{
		node a=q.front();
		q.pop();
		if(a.month<=0)
			continue;
		for(int i=0;i<4;i++)
		{
			int x=a.x+dx[i];
			int y=a.y+dy[i];
			if(x<0||x>=n||y<0||y>=m)
				continue;
			map[x][y]='g';
			node t;
			t.x=x;
			t.y=y;
			t.month=a.month-1;
			q.push(t);
		}
	}
	print();
}
//4 5
//.g...
//.....
//..g..
//.....
//2


 

十、问题描述 

小明要组织一台晚会,总共准备了n个节目。然后晚会的时间有限,他只能最终选择其中的m个节目。这n个节目是按照小明设想的顺序给定的,顺序不能改变。小明发现,观众你对于晚会的喜欢程度与前几个节目的好看成都有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推,小明给每个节目定义了一个好看值,请你帮助小明选择出m个节目,满足他的要求
输入格式:
       输入的第一行包含两个整数n,m,表示节目的数量和要选择的数量。第二行包含n个整数,依次为每个节目的好看值。

输出格式:
       输出一行包含m个整数,为选出的节目的好看值。

样例输入:
5 3
3 1 2 5 4

样例输出:
3 5 4

样例说明

选择了第1,4,5个节目。

评测用例规模与约定:
       对于30%的评测用例,1<=n<=20;
       对于60%的评测用例,1<=n<=100;
       对于所有评测用例,1<=n<=100000,0<=节目的好看值<=100000。
 

/*
错误错误错误错误错误思路: 
用结构体存储每个节目的好看值和下标
先挑选出前m个最好看的界面: 根据好看值降序排序,然后将前m个节目赋值给b 
按照下标升序输出结果: 对b按照下标升序排序,输出 
*/
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
struct node{
	int love;//好看值 
	int index;//下标 
};
int cmd_love(node x,node y){//根据好看值降序排序 
	return x.love>y.love;
}
int cmd_index(node x,node y){//根据下标升序排序 
	return x.index<y.index;
}
int main()
{
	cin>>n>>m;
	node a[n],b[m];
	for(int i=0;i<n;i++)
	{
		cin>>a[i].love;
		a[i].index=i;
	}
	sort(a,a+n,cmd_love);//根据好看值降序排序 
	for(int i=0;i<m;i++)//选取前m个好看的 
		b[i]=a[i];
	sort(b,b+m,cmd_index);
	for(int i=0;i<m;i++)
		cout<<b[i].love<<" ";
	return 0; 
}


 
发布了247 篇原创文章 · 获赞 53 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_42391248/article/details/105064911
今日推荐