蓝桥杯~备战篇

1.c/c++环境安装

蓝桥杯C/C++开发环境:Dev-cpp 5.4.0 或 CodeBlocks 20.03

CodeBlocks 20.03百度网盘地址: https://pan.baidu.com/s/1whzW9XYrxGN_2RylDDzQag 提取码:lqbs

Dev-cpp 5.4.0 百度网盘地址:https://pan.baidu.com/s/1bOCXiI5M7tfWlrTuCZWIiw 提取码:lqbs

个人博客本篇内容地址:https://cxy96.top/note/lanqiao.html

2.基础练习

1.数列排序

时间限制:1.0s   内存限制:512.0MB
问题描述:
  给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200
输入格式:
  第一行为一个整数n。
  第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。
输出格式:
  输出一行,按从小到大的顺序输出排序后的数列。
样例输入:
       5
       8 3 6 4 9
样例输出:
       3 4 6 8 9
1.1 sort函数

sort () 函数是C++ STL标准库中的一个模板函数,可以用来排序

# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;
int main(){
vector <int> b;
int a,c;
cin>>a;
for(int i=0;i<a;i++){
	cin>>c;
	b.push_back(c);
	}
//默认升序排列 
sort(b.begin(),b.end());
//反转一下就是降序排列 
//reverse(b.begin(),b.end()); 
for(int i=0;i<a;i++){
	cout<<b[i]<<" ";
	}
return 0;
} 
1.2 冒泡排序

冒泡排序是一种交换排序。

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

# include <iostream>
# include <vector>
using namespace std;
int main(){
vector <int> b;
int a,c,temp;
cin>>a;
for (int i=0;i<a;i++){
	cin>>c;
	b.push_back(c);
  }
for (int i=1;i<a;i++){
     //优化减少排序次数
     //int swap=0;
	for(int j=0;j<(a-i);j++){
		if(b[j]>b[j+1]){
			temp=b[j];
			b[j]=b[j+1];
			b[j+1]=temp;
                        //swap=1;
			}
		  }
             //if(swap==0) break;
	  }
for(int i=0;i<a;i++){
	cout<<b[i]<<" ";
    }
b.clear();
return 0;
} 
1.3 选择排序

选择排序是一种简单直观的排序算法。 它的工作原理是:第一次从待排序的数据元素中选出最小的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。 以此类推,直到全部待排序的数据元素的个数为零。

# include <iostream>
# include <vector>
using namespace std;
int main(){
vector<int>b;
int a,c,temp;
cin>>a;
for(int i=0;i<a;i++){
	cin>>c;
	b.push_back(c);
	}
for(int i=0;i<a;i++){
	for(int j=i;j<(a-1);j++){
		if(b[j+1]<b[i]){
			temp=b[i];
			b[i]=b[j+1];
			b[j+1]=temp;
			}
		}
	}
for(int i=0;i<a;i++){
	cout<<b[i]<<" "; 
	}
b.clear();
return 0;
} 

2.十六进制转八进制

时间限制:1.0s   内存限制:512.0MB
问题描述:
  给定n个十六进制正整数,输出它们对应的八进制数。
输入格式:
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不         超过100000。
输出格式:
  输出n行,每行为输入对应的八进制正整数。
【注意
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。
样例输入:
  2
  39
  123ABC
样例输出:
  71
  4435274
【提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。
2.1 直观版
# include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
	string tow,eight,sixteen;
	cin>>sixteen;
	for(int j=0;j<sixteen.length();j++){
		switch(sixteen[j]){
			case '0':tow+="0000";break;
			case '1':tow+="0001";break;
			case '2':tow+="0010";break;
			case '3':tow+="0011";break;
			case '4':tow+="0100";break;
			case '5':tow+="0101";break;
			case '6':tow+="0110";break;
			case '7':tow+="0111";break;
			case '8':tow+="1000";break;
			case '9':tow+="1001";break;
			case 'A':tow+="1010";break;
			case 'B':tow+="1011";break;
			case 'C':tow+="1100";break;
			case 'D':tow+="1101";break;
			case 'E':tow+="1110";break;
			case 'F':tow+="1111";break;
			} 
		}
	if (tow.length()%3==1){
		tow="00"+tow;
		}
	if(tow.length()%3==2){
		tow="0"+tow;
	}
	for(int k=0;k<tow.length();k+=3){
		if(tow.substr(k,3)=="000"){
			if (k==0) continue;
			else eight+="0"; 
			}
		else if(tow.substr(k,3)=="001"){
			eight+="1";
			}
		else if(tow.substr(k,3)=="010"){
			eight+="2";
			}
		else if(tow.substr(k,3)=="011"){
			eight+="3";
			}
		else if(tow.substr(k,3)=="100"){
			eight+="4";
			}
		else if(tow.substr(k,3)=="101"){
			eight+="5";
			}
		else if(tow.substr(k,3)=="110"){
			eight+="6";
			}
		else if(tow.substr(k,3)=="111"){
			eight+="7";
			}
		}
	cout<<eight<<endl;
	}
return 0;
} 
2.2 简洁版
# include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
	string tow,eight,sixteen;
	cin>>sixteen;
	for(int j=0;j<sixteen.length();j++){
		switch(sixteen[j]){
			case '0':tow+="0000";break;
		        case '1':tow+="0001";break;
			case '2':tow+="0010";break;
			case '3':tow+="0011";break;
			case '4':tow+="0100";break;
			case '5':tow+="0101";break;
			case '6':tow+="0110";break;
			case '7':tow+="0111";break;
			case '8':tow+="1000";break;
			case '9':tow+="1001";break;
			case 'A':tow+="1010";break;
			case 'B':tow+="1011";break;
			case 'C':tow+="1100";break;
			case 'D':tow+="1101";break;
			case 'E':tow+="1110";break;
			case 'F':tow+="1111";break;
			}
		}
		if(tow.length()%3==1) tow="00"+tow;
		else if(tow.length()%3==2) tow="0"+tow;
		if(!(tow[0]=='0'&&tow[1]=='0'&&tow[2]=='0')){
			eight+=(tow[0]-'0')*4+(tow[1]-'0')*2+tow[2];
		}
		for(int k=3;k<tow.length();k+=3){
			eight+=(tow[k]-'0')*4+(tow[k+1]-'0')*2+tow[k+2];
		}
		cout<<eight<<endl;
	}
	return 0;
}

3. 十六进制转十进制

时间限制:1.0s   内存限制:512.0MB
问题描述:
  从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。
  注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。
样例输入:
        FFFF
样例输出:
        65535
# include<iostream>
using namespace std;
int main(){
	string sixteen,tow;
	long long ten=0;
	cin>>sixteen;
	for(int i=0;i<sixteen.length();i++){
		switch(sixteen[i]){
			case '0': tow+="0000";break;
			case '1': tow+="0001";break;
			case '2': tow+="0010";break;
			case '3': tow+="0011";break;
			case '4': tow+="0100";break;
			case '5': tow+="0101";break;
			case '6': tow+="0110";break;
			case '7': tow+="0111";break;
			case '8': tow+="1000";break;
			case '9': tow+="1001";break;
			case 'A': tow+="1010";break;
			case 'B': tow+="1011";break;
			case 'C': tow+="1100";break;
			case 'D': tow+="1101";break;
			case 'E': tow+="1110";break;
			case 'F': tow+="1111";break;
		}
	}
	for(int j=0;j<tow.length();j++){
		if(tow[j]=='0') continue;
		long long x=1;
		for(int k=1;k<(tow.length()-j);k++) x*=2;
		ten+=(tow[j]-'0')*x;
		}
	cout<<ten<<endl;
	return 0;
} 

4. 十进制转十六进制

时间限制:1.0s   内存限制:512.0MB
问题描述:
  十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。给出一个非负整数,将它表示成十六进制的形式。
输入格式:
  输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647
输出格式:
  输出这个整数的16进制表示
样例输入:
       30
样例输出:
       1E
# include <iostream>
# include <algorithm>
using namespace std;
int main(){
	int ten;
	string sixteen,tow,m; 
	cin>>ten;
	if(ten==0){
		cout<<0;
		return 0;
	}
	while(ten!=0){
		tow+=(ten%2)+'0';
		ten/=2;
	}
	reverse(tow.begin(),tow.end()); 
	if(tow.length()%4==1) tow="000"+tow;
	else if(tow.length()%4==2) tow="00"+tow;
	else if(tow.length()%4==3) tow="0"+tow;
	for(int i=0;i<tow.length();i+=4){
		m=(tow[i]-'0')*8+(tow[i+1]-'0')*4+(tow[i+2]-'0')*2+tow[i+3];
		if(tow[0]==0&&tow[1]==0&&tow[2]==0&&tow[3]==0)
			continue;
		else if(m <="9"){
			sixteen+=m;
		}
		else if(tow.substr(i,4)=="1010"){
			sixteen+='A';
		}
		else if(tow.substr(i,4)=="1011"){
			sixteen+='B';
		}
		else if(tow.substr(i,4)=="1100"){
			sixteen+='C';
		}
		else if(tow.substr(i,4)=="1101"){
			sixteen+='D';
		}		
		else if(tow.substr(i,4)=="1110"){
			sixteen+='E';
		}
		else if(tow.substr(i,4)=="1111"){
			sixteen+='F';
		}
	}
cout<<sixteen;
return 0;
} 

5. 特殊回文数

时间限制:1.0s   内存限制:512.0MB
问题描述:
  123321是一个非常特殊的数,它从左边读和从右边读是一样的。
  输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
输入格式:
  输入一行,包含一个正整数n。
输出格式:
  按从小到大的顺序输出满足条件的整数,每个整数占一行。
样例输入:
       52
 样例输出:
       899998
       989989
       998899
数据规模和约定:
    1<=n<=54。
# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;
int main(){
vector <int> b;
int n,out;
cin>>n;
for(int i=1;i<=9;i++){
	for(int j=0;j<=9;j++){
		for(int k=0;k<=9;k++){
			if(2*(i+j+k)==n){
				out=100000*i+10000*j+1000*k+100*k+10*j+i;
				b.push_back(out);
				}
			if(2*(i+j)+k==n){
				out=10000*i+1000*j+100*k+10*j+i;
				b.push_back(out); 
				}
			}
		}
	}
sort(b.begin(),b.end());
//unique只能移除相邻的重复元素,所以在去重前要先排序  且unique不改变元素的个数,会有残留的数据遗留下来 
//unique(b.begin(),b.end());
//erase函数清除遗留数据
b.erase(unique(b.begin(),b.end()),b.end());
for(int i=0;i<b.size();i++){
	cout<<b[i]<<endl;
	}
return 0;
}

6. 回文数

时间限制:1.0s   内存限制:512.0MB
问题描述:
  1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。
输出格式:
  按从小到大的顺序输出满足条件的四位十进制数。
# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;
int main(){
vector<int>b;
int n;
for(int i=1;i<=9;i++){
	for(int j=0;j<=9;j++){
		n=i*1000+j*100+j*10+i;
		b.push_back(n);
		}
	}
sort(b.begin(),b.end());
for(int i=0;i<b.size();i++){
	cout<<b[i]<<endl; 
	}
return 0;
} 

7. 特殊的数字

时间限制:1.0s   内存限制:512.0MB
问题描述:
  153是一个非常特殊的数,它等于它的每位数字的立方和,即153=1*1*1+5*5*5+3*3*3。编程求所有满足这种条件          的三位十进制数。
输出格式:
  按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。
# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;
int main(){
vector <int> b;
int n;
for(int i=1;i<=9;i++){
	for(int j=0;j<=9;j++){
		for(int k=0;k<=9;k++){
			n=i*100+j*10+k;
			if((i*i*i+j*j*j+k*k*k)==n) b.push_back(n);
		}
	}
}
sort(b.begin(),b.end());
for(int i=0;i<b.size();i++){
	cout<<b[i]<<endl;
}
return 0;
}

8. 杨辉三角

时间限制:1.0s   内存限制:256.0MB
问题描述:

杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数。

它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。

下面给出了杨辉三角形的前4行

   1

  1 1

 1 2 1

1 3 3 1

给出n,输出它的前n行。

输入格式:

输入包含一个数n。

输出格式:
输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面输出多余的空格。
样例输入:
4
样例输出:
1
1 1
1 2 1
1 3 3 1
数据规模与约定:
1 <= n <= 34
# include <iostream>
# include <vector> 
using namespace std;
int main(){
int n;
cin>>n;
//创建n行二维数组 
vector<vector<int> > b(n);
//resize给每行数组指定列数 
for(int i=0;i<n;i++) b[i].resize(i+1);
b[0][0]=1;
for(int i=1;i<n;i++){
	for(int k=0;k<(i+1);k++){
		if(k==0||k==i){
			b[i][k]=1;
		}
		else{
			b[i][k]=b[i-1][k-1]+b[i-1][k];
		}
	}
}
for(int i=0;i<n;i++){
	for(int k=0;k<(i+1);k++){
		cout<<b[i][k]<<" ";
	}
	cout<<endl; 
}
return 0;
}

9. 查找整数

时间限制:1.0s   内存限制:256.0MB
问题描述:

给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。

输入格式:

第一行包含一个整数n。

第二行包含n个非负整数,为给定的数列,数列中的每个数都不大于10000。

第三行包含一个整数a,为待查找的数。

输出格式:
如果a在数列中出现了,输出它第一次出现的位置(位置从1开始编号),否则输出-1。
样例输入:
6
1 9 4 8 3 9
9
样例输出:
2
数据规模与约定:
1 <= n <= 1000。
# include <iostream>
# include <vector>
using namespace std;
int main(){
int n,a,m;
vector <int> b;
cin>>n; 
for(int i=0;i<n;i++){
	cin>>a;
	b.push_back(a);
	}
cin>>m;
for(int i=0;i<n;i++){
	if(b[i]==m){
		cout<<(i+1);
		break;
		}
	else if (i==(n-1)){
		cout<<-1;
		}
	}
return 0;
} 

10. 数列特征

时间限制:1.0s   内存限制:256.0MB
问题描述:

给出n个数,找出这n个数的最大值,最小值,和。

输入格式:

第一行为整数n,表示数的个数。

第二行有n个数,为给定的n个数,每个数的绝对值都小于10000。

输出格式:
输出三行,每行一个整数。第一行表示这些数中的最大值,第二行表示这些数中的最小值,第三行表示这些数的和。
样例输入:
5
1 3 -2 4 5
样例输出:
5
-2
11
数据规模与约定:
1 <= n <= 10000。
# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;
int main(){
int n,m,sum=0;
vector <int> b;
cin>>n;
for(int i=0;i<n;i++){
	cin>>m;
	b.push_back(m);
	sum+=m;
}
sort(b.begin(),b.end());
if (b.size()==1) cout<<b[0]<<endl<<b[0]<<endl<<b[0];
else cout<<b[n-1]<<endl<<b[0]<<endl<<sum;
return 0;
}

11. 字母图形

时间限制:1.0s   内存限制:256.0MB
问题描述:

利用字母可以组成一些美丽的图形,下面给出了一个例子:

ABCDEFG

BABCDEF

CBABCDE

DCBABCD

EDCBABC

这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。

输入格式:
输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。
输出格式:
输出n行,每个m个字符,为你的图形。
样例输入:
5 7
样例输出:
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
数据规模与约定:
1 <= n, m <= 26。
# include <iostream>
# include <vector>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector <vector<char> > b(n);
for(int i=0;i<n;i++){
	b[i].resize(m);
	b[i][0]='A'+i;
	if(i==0){
		for(int j=1;j<m;j++)b[i][j]='A'+j;
	} 
}
for(int i=1;i<n;i++){
	for(int j=1;j<m;j++){
		if(j<i) b[i][j]=b[i][0]-j;
		else b[i][j]=b[i-1][j-1];
	}
}
for(int i=0;i<n;i++){
	for(int j=0;j<m;j++){
		cout<<b[i][j];
	}
	cout<<endl;
}
return 0;
} 

12. 01字符串

时间限制:1.0s   内存限制:256.0MB
问题描述:
对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能。它们的前几个是:
00000
00001
00010
00011
00100
请按从小到大的顺序输出这32种01串。
输入格式:
本试题没有输入。
输出格式:
输出32行,按从小到大的顺序每行一个长度为5的01串。
样例输出:
00000
00001
00010
00011
<以下部分省略>
# include <iostream>
using namespace std;
int main(){
for(int a=0;a<2;a++){
	for(int b=0;b<2;b++){
		for(int c=0;c<2;c++){
			for(int d=0;d<2;d++){
				for(int e=0;e<2;e++){
					cout<<a<<b<<c<<d<<e<<endl;
				}
			}
		}
	}
}
return 0;
} 

13. 闰年判断

时间限制:1.0s   内存限制:256.0MB
问题描述:
给定一个年份,判断这一年是不是闰年。
当以下情况之一满足时,这一年是闰年:
1. 年份是4的倍数而不是100的倍数;
2. 年份是400的倍数。
其他的年份都不是闰年。
输入格式:
输入包含一个整数y,表示当前的年份。
输出格式:
输出一行,如果给定的年份是闰年,则输出yes,否则输出no。
说明:当试题指定你输出一个字符串作为结果(比如本题的yes或者no,你需要严格按照试题中给定的大小写,写错大小写将不得分。
 
样例输入:
2013
样例输出:
no
样例输入:
2016
样例输出:
yes
数据规模与约定:
1990 <= y <= 2050。
# include <iostream>
using namespace std;
int main(){
int y;
cin>>y;
if((y%4==0) && (y%100!=0)){
	cout<<"yes";
}
else if(y%400==0){
	cout<<"yes";
}
else{
	cout<<"no";
}
return 0;
} 

14. Fibonacci数列

时间限制:1.0s   内存限制:256.0MB
问题描述:
Fibonacci数列的递推公式为:F n =F n-1 +F n-2 ,其中F 1 =F 2 =1。
当n比较大时,F n 也非常大,现在我们想知道,F n 除以10007的余数是多少。
输入格式:
输入包含一个整数n。
输出格式:
输出一行,包含一个整数,表示F n除以10007的余数。
说明:在本题中,答案是要求Fn除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出Fn的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。
 
样例输入:
10
样例输出:
55
样例输入:
22
样例输出:
7704
数据规模与约定:
1 <= n <= 1,000,000。
14.1 暴力递归

暴力递归的方法很慢,实间复杂度O(2n) 在40左右时就会感到明显的迟缓,该方法无法通过检测,这里只是提供一个递归思路。

# include <iostream>
using namespace std;
int Fib(int n){
	if (n==1||n==2){
		return 1;
	}
	else{
		return ((Fib(n-1)+Fib(n-2))%10007);
	}
}
int main(){
int n;
cin>>n;
cout<<Fib(n);
return 0;
}
14.2 动态规划

空间复杂度O(n

# include <iostream>
# include <vector>
using namespace std;
int main(){
int n1=1,n2=1,num=0,n;
vector <int> b;
cin>>n;
if(n<=2){
	cout<<1;
}
else{
	b.push_back(1);
	b.push_back(1);
	for(int i=2;i<n;i++){
		num=(b[i-1]+b[i-2])%10007;
		b.push_back(num);
	}
	cout<<b[n-1];
}
return 0;
}

空间复杂度O(1) 

# include <iostream>
using namespace std;
int main(){
int n,a=1,b=1;
cin>>n;
if(n<=2){
	cout<<1;
}
else{
	for(int i=2;i<n;i++){
		int temp=a;
		a=b;
		b=(a+temp)%10007;
	}
	cout<<b;
}
return 0;
} 

15. 圆的面积

这里要求对小数点精确控制,c++控制方法参考:https://blog.csdn.net/gyxx1998/article/details/103337790

时间限制:1.0s   内存限制:256.0MB
问题描述:
给定圆的半径r,求圆的面积。
输入格式:
输入包含一个整数r,表示圆的半径。
输出格式:
输出一行,包含一个实数,四舍五入保留小数点后7位,表示圆的面积。
说明:在本题中,输入是一个整数,但是输出是一个实数。
对必须严格的输出7位小数,输出过多或者过少的小数位数都是不行的,都会被认为错误。
实数输出的问题如果没有特别说明,舍入都是按四舍五入进行。
样例输入:
4
样例输出:
50.2654825
数据规模与约定:
1 <= r <= 10000。
提示:
本题对精度要求较高,请注意π的值应该取较精确的值。你可以使用常量来表示π,比如PI=3.14159265358979323,也可以使用数学公式来求π,比如PI=atan(1.0)*4。
# include <iostream>
# include <iomanip>
using namespace std;
int main(){
const double PI=3.14159265358979323;
int r;
cin>>r;
cout<<fixed<<setprecision(7)<<PI*r*r;
return 0;
} 

16. 序列求和

时间限制:1.0s   内存限制:256.0MB
问题描述:
求1+2+3+...+n的值。
输入格式:
输入包括一个整数n。
输出格式:
输出一行,包括一个整数,表示1+2+3+...+n的值。
样例输入:
4
样例输出:
10
样例输入:
100
说明: 有一些试题会给出多组样例输入输出以帮助你更好的做题。
 
一般在提交之前所有这些样例都需要测试通过才行,但这不代表这几组样例数据都正确了你的程序就是完全正确的,潜在的错误可能仍然导致你的得分较低。
 
样例输出:
5050
数据规模与约定:
1 <= n <= 1,000,000,000
# include <iostream>
using namespace std;
int main(){
int n;
long long num=0;
cin>>n;
for(int i=1;i<=n;i++){
	num+=i;
}
cout<<num;
return 0;
}

3.算法训练

3.1 动态规划

3.1.1 拿金币
时间限制:1.0s   内存限制:256.0MB
问题描述:
  有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式:
  第一行输入一个正整数n。
  以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式:
  最多能拿金币数量。
样例输入:
3
1 3 3
2 2 2
3 1 2
样例输出:
11
数据规模和约定:
  n<=1000
# include <iostream>
# include <algorithm>
using namespace std;
int main(){
int n;
cin>>n;
int arr[n][n];
for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
		cin>>arr[i][j];
	}
}
for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
		if(i==0&&j==0) continue;
		else if(i==0&&j!=0) arr[i][j]+=arr[i][j-1];
		else if(j==0&&i!=0) arr[i][j]+=arr[i-1][j];
		else arr[i][j]+=max(arr[i-1][j],arr[i][j-1]);
	}
} 
cout<<arr[n-1][n-1];
return 0;
} 
3.1.2 印章
时间限制:1.0s   内存限制:256.0MB
问题描述:
  共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
输入格式:
  一行两个正整数n和m
输出格式:
  一个实数P表示答案,保留4位小数。
样例输入:
2 3
样例输出:
0.7500
数据规模和约定:
  1≤n,m≤20
# include <iostream>
# include <cmath>
# include <iomanip>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
double db[m+1][n+1];
double p=1.0/n;
for(int i=1;i<=m;i++){
	for(int j=1;j<=n;j++){
		if(i<j) db[i][j]=0;
		else if(j==1) db[i][j]=pow(p,i-1);  //p的i-1次方
		else{
			db[i][j]=db[i-1][j-1]*((n-j+1)*p)+db[i-1][j]*(j*p);
		}
	}
}
cout<<fixed<<setprecision(4)<<db[m][n];
return 0;
}
3.1.3 无聊的逗

运用了01背包问题的思想,推荐:https://zhuanlan.zhihu.com/p/139368825

时间限制:1.0s 内存限制:256.0MB
问题描述:
  逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中。不过他想到了一个游戏来使他更无聊。他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的情况下长度最长是多少。
输入格式:
  第一行一个数n,表示n个棍子。第二行n个数,每个数表示一根棍子的长度。
输出格式:
  一个数,最大的长度。
样例输入:
4
1 2 3 1
样例输出:
3
数据规模和约定
 n<=15
#include <bits/stdc++.h>
using namespace std;
int canPartition(vector<int>v){
	int sum,target,maxNum,n;
	n = v.size();
	if (n < 2) return 0;
	sum = accumulate(v.begin(),v.end(),0);
	
	target = sum / 2;
	maxNum = *max_element(v.begin(),v.end());
	if(maxNum > target) return 0;
	vector<vector<int> > dp(n,vector<int>(target+1));
	// 初始化背包
	for(int i=0;i<n;i++) dp[i][0] = 0;
	for(int j=v[0];j<=target;j++) dp[0][j]=v[0]; 
	for(int i=1;i<n;i++){
		for(int j=1;j<=target;j++){
			if(v[i]>j) dp[i][j]=dp[i-1][j];
			else dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+v[i]);
		}
	}
	return dp[n-1][target]==target?target:0;
}
int main(){
	int n,sum,ans=0,i=0;
	cin>>n;
	vector<int>v(n);
	for(int i=0;i<n;i++) cin>>v[i];
	sort(v.begin(),v.end());
	sum=accumulate(v.begin(),v.end(),0);
	if ((sum&1)==0) ans=canPartition(v);
	while (i < v.size()) {
        if (((sum - v[i])&1) == 0) {
            v.erase(v.begin()+i); 
            ans = max(canPartition(v), ans); 
            i = 0; 
            sum=accumulate(v.begin(),v.end(),0);
            continue;
        }
        i++;
    }
	cout<<ans;
	return 0;
}

  • 空间优化
#include <bits/stdc++.h>
using namespace std;
int canPartition(vector<int>v){
	int sum,target,maxNum,n;
	n = v.size();
	if (n < 2) return 0;
	sum = accumulate(v.begin(),v.end(),0);
	
	target = sum / 2;
	maxNum = *max_element(v.begin(),v.end());
	if(maxNum > target) return 0;
	vector<int> dp(vector<int>(target+1));
	// 初始化背包
	dp[0] = 0;
	for(int i=1;i<n;i++){
		for(int j=target;j>=v[i];j--){
			dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
		}
	}
	return dp[target]==target?target:0;
}
int main(){
	int n,sum,ans=0,i=0;
	cin>>n;
	vector<int>v(n);
	for(int i=0;i<n;i++) cin>>v[i];
	sort(v.begin(),v.end());
	sum=accumulate(v.begin(),v.end(),0);
	if ((sum&1)==0) ans=canPartition(v);
	while (i < v.size()) {
        if (((sum - v[i])&1) == 0) {
            v.erase(v.begin()+i); 
            ans = max(canPartition(v), ans); 
            i = 0; 
            sum=accumulate(v.begin(),v.end(),0);
            continue;
        }
        i++;
    }
	cout<<ans;
	return 0;
}

3.2 查找

3.2.1 区间k大数查询
时间限制:1.0s   内存限制:256.0MB
问题描述:
给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
输入格式:
第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
输出格式:
总共输出m行,每行一个数,表示询问的答案。
样例输入:
5
1 2 3 4 5
2
1 5 2
2 3 2
样例输出:
4
2
数据规模与约定:
对于30%的数据,n,m<=100;
对于100%的数据,n,m<=1000;
保证k<=(r-l+1),序列中的数<=10 6
# include <iostream>
# include <algorithm>
using namespace std;
int main(){
int n,m;
cin>>n;
int arr1[n];
for(int i=0;i<n;i++){
	cin>>arr1[i];
}
cin>>m;
int arr2[m][3];
for(int i=0;i<m;i++){
	for(int j=0;j<3;j++){
		cin>>arr2[i][j];
	}
}
for(int i=0;i<m;i++){
	  int len=arr2[i][1]-arr2[i][0]+1;
	  if (len==1)cout<<arr1[arr2[i][0]-1]<<endl;
	  else{
	  	int arr3[len];
	  	for(int j=0;j<len;j++){
	  		arr3[j]=arr1[arr2[i][0]-1+j];
	  	}
	  	sort(arr3,arr3+len);
	  	cout<<arr3[len-arr2[i][2]]<<endl;
	  }
}
return 0;
} 
3.2.2 数字游戏

本题用到了c++的一个排序函数 next_permutation(a,a+n),用法可参考:

https://www.cnblogs.com/My-Sunshine/p/4985366.html

时间限制:1.0s 内存限制:256.0MB
问题描述
  给定一个1~N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列都比上一次的序列长度少1,最终只剩一个数字。
  例如:
  3 1 2 4
  4 3 6
  7 9
  16
  现在如果知道N和最后得到的数字sum,请求出最初序列a[i],为1~N的一个排列。若有多种答案,则输出字典序最小的那一个。数据保证有解。
输入格式
  第1行为两个正整数n,sum
输出格式
  一个1~N的一个排列
样例输入
4 16
样例输出
3 1 2 4
数据规模和约定
0<n<=10
# include <iostream>
# include <algorithm>
using namespace std;
int main(){
int n,num;
cin>>n>>num;
int arr1[n],arr2[n];
for(int i=0;i<n;i++){
	arr1[i]=i+1;
}
do{
	for(int i=0;i<n;i++){
		arr2[i]=arr1[i];
	}
	for(int i=n;i>1;i--){
		for(int j=0;j<i-1;j++){
			arr2[j]=arr2[j]+arr2[j+1];
		}
	}
	if(num==arr2[0]){
		for(int i=0;i<n;i++){
			cout<<arr1[i]<<" ";
		}
		break;
	}
}while(next_permutation(arr1,arr1+n));
return 0;
} 
3.2.3 礼物
时间限制:1.0s   内存限制:256.0MB
问题描述:
  JiaoShou在爱琳大陆的旅行完毕,即将回家,为了纪念这次旅行,他决定带回一些礼物给好朋友。
  在走出了怪物森林以后,JiaoShou看到了排成一排的N个石子。
  这些石子很漂亮,JiaoShou决定以此为礼物。
  但是这N个石子被施加了一种特殊的魔法。
  如果要取走石子,必须按照以下的规则去取。
  每次必须取连续的2*K个石子,并且满足前K个石子的重量和小于等于S,后K个石子的重量和小于等于S。
  由于时间紧迫,Jiaoshou只能取一次。
  现在JiaoShou找到了聪明的你,问他最多可以带走多少个石子。
输入格式:
  第一行两个整数N、S。
  第二行N个整数,用空格隔开,表示每个石子的重量。
输出格式:
  第一行输出一个数表示JiaoShou最多能取走多少个石子。
样列输入:
  8 3
  1 1 1 1 1 1 1 1
样列输出:
  6
样列解释:
  任意选择连续的6个1即可。
数据规模和约定:
  对于20%的数据:N<=1000
  对于70%的数据:N<=100,000
  对于100%的数据:N<=1000,000,S<=10^12,每个石子的重量小于等于10^9,且非负
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
long long a[N],val[N],S;
int n,k,l,r;
bool check(int tem){
    for(int i=tem;i<=n-tem;i++){
        if(val[i]-val[i-tem]<=S&&val[i+tem]-val[i]<=S){
			// 当答案存在时 返回true
            return true;
        }
    }
    return false;
}
int main(){
    cin>> n >> S;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        val[i]=val[i-1]+a[i];//求前缀和      
    }
    l=1,r=1e6;
    while(l<r){  
    	// 右移运算符 相当于除以2 效率更高 
        int mid=(l+r+1)>>1;
        if(check(mid))
            l=mid;
        else 
            r=mid-1;
    }
    cout<<2*l;
    return 0;
}

3.3 贪心算法

3.3.1 最大最小公倍数

貌似好像是数据问题,练习系统只能得60分。

时间限制:1.0s   内存限制:256.0MB
问题描述:
已知一个正整数N,问从1~N中任选出三个数,他们的最小公倍数最大可以为多少。
输入格式:
输入一个正整数N。
输出格式:
输出一个整数,表示你找到的最小公倍数。
样例输入:
9
样例输出:
504
数据规模与约定:
1 <= N <= 10 6
# include <iostream>
using namespace std;
int main(){
long long n,num;
cin>>n;
if(n%2!=0) num=n*(n-1)*(n-2);
else{
	int i=3;
	while(1){
		if(((n-i)%i)!=0){
		num=n*(n-1)*(n-i);
		break;
		}
		else i+=2;
	}
}
cout<<num;
return 0;
}
  • 27
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旅程@.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值