第十一屆藍橋杯模擬賽軟件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; 
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章