蓝桥杯2013年B组省赛解析

总结

01、高斯日记 手算/excel/编程(枚举,模拟翻日历)
坑点:第一天

02、马虎的算式 枚举+check

03、第39级台阶 普通走台阶的变体–递归思维

***04、黄金连分数 黄金分割与斐波那契数列,大数加法,大数除法(减法)
n取多少,100位的小数才稳定呢

05、前缀判断 C语言字符出处理,比对+偏移

06、三部排序 快速排序的变体 单指针 双指针 三指针

07、错误票据 排序+遍历

*08、翻硬币 找规律

***09、带分数 全排列+字符串切割
全排列+字符转整数(不能用atoi函数)——坑很大

10、连号区间数 简单枚举

1.高斯日记(出生当天记为第一天)
日期API和excel无法处理和计算1970年以前的日期。
在这里插入图片描述
解法1、excel
在这里插入图片描述
在这里插入图片描述
解法2、简单枚举
可测试题目所给的数据,得到出生那天是否算第一天。

#include<cstdio> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
using namespace std;
bool isleaperyear(int y){
		return ((y%4==0)&&(y%100!=0))||(y%400==0);
	}
int main(){
	int y=1777;
	int m=4;
	int d=30;

	for(int i=0;i<8112;i++ ){
		d++;
		if(m==12&&d==32){
			y++;
			m=1;
			d=1;
		continue;
		}
		if((m==1||m==3||m==5||m==7||m==8||m==10||m==12)&&d==32)
		{
			m++;
			d=1;
			continue;
		}
		if((m==4||m==6||m==9||m==11)&&d==31)
		{
			m++;
			d=1;
			continue;
		}
		if(m==2&&isleaperyear(y)&&d==30){
			m++;
			d=1;
			continue;
			
		}
			if(m==2&&!isleaperyear(y)&&d==29){
			m++;
			d=1;
			continue;
			
		}
		
	}
	printf("%d-%d-%d",y,m,d);
		return 0;
}

2.马虎的算式
枚举

#include<cstdio> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
using namespace std;
int main(){
	int count=0;
	for(int a=1;a<10;a++){
		for(int b=1;b<10;b++){
			if(b!=a)
				for(int c=1;c<10;c++){
					if(c!=a&&c!=b)
						for(int d=1;d<10;d++){
							if(d!=a&&d!=b&&d!=c)
								for(int e=1;e<10;e++){
									if(e!=a&&e!=b&&e!=c&&e!=d){
										if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e))
										count++;
									}
								
							
						
					}
				}
			}
		}
	}
	printf("%d",count) ;
	return 0;
}

3.第39级台阶
背dfs的模板

#include<cstdio> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
using namespace std;
int ans;
//n 剩下的阶梯数
//step 已经走的步数 
void dfs(int n,int step){
if(n<0) return;//边界条件
if(n==0&&step%2==0) ans++;
dfs(n-1,step+1);//递归 
dfs(n-2,step+1); 
} 
int main(){
	dfs(39,0);
	 printf("%d",ans); 
	return 0;
}

4、黄金连分数(秒出大数的加法)
(1)转为求斐波那契数列的n和n+1项
(2)n取多少?再增加n,小数点后的101位没有发生变化。
(3)不能用c语言定义的整数型直接运算,而要手工地写大数加法和除法(减法)

#include<cstdio> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<deque>
#include<vector>
#include<stack>
#include<sstream> 
#include<iostream>
using namespace std;

int n=400;//稳定 
string add(string a,string b){
	a=a.substr(a.find_first_not_of('0'));//删掉前面的0 
	b=b.substr(b.find_first_not_of('0'));//删掉前面的0
	long long lenA=a.length();
	long long lenB=b.length();
	long long len=max(lenA,lenB)+10;
	//翻转,便于从低位逐步求和 
	reverse(a.begin(),a.end());
	reverse(b.begin(),b.end());
	string ans(len,'0');//初始化ans为len长,全部字符为0
//把a拷贝到ans中
for(int i=0;i<lenA;i++){
	ans[i]=a[i]; 
} 
int tmp=0; //tmp是上一位相加后的进位 
for(int j=0;j<len;j++){
	if(j<b.length()) 
	tmp+=(ans[j]-'0')+(b[j]-'0');//假设为18 
	else
	tmp+=(ans[j]-'0');
	ans[j]=tmp%10+'0';//取个位  8
	tmp/=10;//取十位  1 
}
reverse(ans.begin(),ans.end());
	ans=ans.substr(ans.find_first_not_of('0'));//删掉前面的0 
	return ans; 
}
int cmp(string a,string b){
	unsigned long i1=a.find_first_not_of('0');
    unsigned long i2=b.find_first_not_of('0');
    
    if(i1==string::npos) a='0';
	else a.substr(i1); 
	
	if(i2==string::npos) b='0';
	else b.substr(i2); 
	
	if(a.length()>b.length()) return 1;
	else if(a.length()<b.length()) return -1;
	else{//长度相等
	if(a<b) return -1;
	if(a>b) return 1;
	else return 0;	
	}
	
}
//此处a一定大于等于b 
string subtract(string a,string b){
	//完整的减法里面,a可以小于b,这时结果为负数,交换a,b进行下面的代码
	//1.翻转
	reverse(a.begin(),a.end()); 
	reverse(b.begin(),b.end());
	//2.按位做减法
	//拷贝a到ans中
	//string ans=a;
	for(int i=0;i<b.length();i++){
		if(a[i]>=b[i]){
			a[i]=a[i]-b[i]+'0';
		}else
		{
			//就要借
			int k=1;
			 while(a[i+k]=='0'){
			 	a[i+k]='9';
			 	k++;
			 } 
			 //这里可以保证i+k这一位上不是0
			 a[i+k]= a[i+k]-'1'+'0';
			 a[i]=(a[i]-'0'+10-(b[i]-'0'))+'0';
		}
	}
	reverse(a.begin(),a.end());
	if(a.find_first_not_of('0')==string::npos) return "0";//从头到尾都找不到0 
	return a.substr(a.find_first_not_of('0'));
}
void i2s(int num,string &str)
{
    stringstream ss;
    ss << num;
    ss >> str;
}
//转换成减法 
string divide(string a,string b){
//只考虑a<b的情况
string ans="0.";
//转换成减法
for(int i=0;i<101;i++){//101次
	a.append("0");
	int t=0;
while(cmp(a,b)>=0){//a>=b
	a=subtract(a,b);//不停地做减法 
	t++;//记录减法做了多少次 
} 
string t_str;
i2s(t,t_str);//转为str 
ans.append(t_str);
} 
	return ans;
}

int main(){
	string a="41";
	string b="23";
cout<<subtract(a,b)<<endl;
	for(int i=3;i<=n;i++){
		string temp=b;//拷贝b
		b=add(a,b); 
		a=temp;
		//cout<<b<<""<<endl;
	}
	//a,b是斐波那契的n-1和n项
	string ans=divide(a,b); 
cout<<ans<<endl;
cout<<ans.length()-2<<endl;
	return 0;
}

5、前缀判断(代码填空)
先编译通过,导入头文件,再看逻辑,验证

#include<iostream>
using namespace std;
char* prefix(char* haystack_start,char*needle_start){
	char* haystack=haystack_start;//母串 
	char* needle=needle_start;//前缀
	
	while(*haystack&&*needle){//两个指针都没有越界
	 //移动指针并判断
	 if(*(haystack++)!=*(needle++))  return NULL;	}//if里面是填空位置 
	if(*needle) return NULL;
	return haystack_start;
	 
} 
int main(){
	cout<<prefix("abd123","abd")<<endl;
	return 0;
} 

6.三部排序(代码填空)
快速排序

#include<iostream>
using namespace std;
void sort3p(int *x,int len){
	int mod=0;
	int left=0;
	int right=len-1;
	
	while(mod<=right){
		if(x[mod]<0){
			int t=x[left];
			x[left]=x[mod];
			x[mod]=t;
			left++;
			mod++;
		}
		else if(x[mod]>0){
			int t=x[right];
			x[right]=x[mod];
			x[mod]=t;
			right--;
		}else{
			//==0
			mod++;
		}
		}
	} 
 
int main(){
	int arr[]={25,34,65,7,2,-1,-9};
	sort3p(arr,7);
	for(int i=0;i<7;i++){
		cout<<arr[i]<<" ";
	} 
	return 0;
}

7、错误票据

#include<cstdio> 
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<iostream> 
using namespace std;
const int MaxN=10000; 
int line;
int data[MaxN]; 
void s2i(string &str,int &num){
	stringstream ss;
	ss<<str;
	ss>>num;
}
int main(){
	scanf("%d",&line);
	getchar();//去掉换行符
	int index=0;
	for(int i=0;i<line;++i){
		string s;
		getline(cin,s);
		istringstream iss(s);//把s封装到iss 
		string tmp;
		while(getline(iss,tmp,' ')){//getline自带分割功能,输入流要是iss,每次切割封装到tmp当中
		 s2i(tmp,data[index++]);//先取值,在加加
		  
			
		}
	} 
	//最终index就是数据的个数 
//	cout<<index<<endl;
	//排序 
	sort(data,data+index);
	int a,b;
	for(int i=1;i<index;i++){
		if(data[i]==data[i-1]+2) a=data[i-1];
		if(data[i]==data[i-1]) b=data[i];
	} 
	printf("%d %d",a,b);
	return 0;
	
}

8、翻硬币

#include<iostream>
using namespace std;

int main(){
	string src;
	string target;
	getline(cin,src);
	getline(cin,target);
	int n=src.length();
	int start=-1;
	int ans=0; 
	for(int i=0;i<n;++i){
		src[i]!=target[i];
    if(start==-1)//还没标记带一个标记
	{
		start=i;
	} 
	else//第一个位置已经标记,现在已经找到第二个位置 
	{
		ans+=(i-start);
		start=-1; 
	} 
	}
	cout<<ans<<endl;
	return 0;
}

9、带分数
暴力枚举(使用substr会超时)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
 
int main(){
	int n,ans=0;
	scanf("%d",&n);
	string s="123456789";
	do{
		for(int i=1;i<=7;i++){//加号前的串长度 
			string a=s.substr(0,i);
			//字符串转为整数
			int inta=atoi(a.c_str()); 
			if(inta>=n)break;
			
			//插入除号
			for(int j=1;j<9-i-1;j++) {//加号、除号两个串之间的长度 
			string b=s.substr(i,j);
			string c=s.substr(i+j);//这是除号后面的串
			int intb=atoi(b.c_str());
			int intc=atoi(c.c_str());
		    if(intb%intc==0&&inta+intb/intc==n) ans++;	
		
			} 
		}
	}while(next_permutation(s.begin(),s.end()));
	printf("%d",ans);
	return 0;
} 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
 int parse(const char *arr,int pos,int len){
 	int ans=0;
 	int t=1;
 	for(int i=pos+len-1;i>=pos;i--){
 		ans+=(arr[i]-'0')*t;
 		t*=10;
 	}
 	return ans;
 } 
int main(){
	int n,ans=0;
	scanf("%d",&n);
	string s="123456789";
	
	do{
	    const char *str=s.c_str();//返回const* 
		for(int i=1;i<=7;i++){//加号前的串长度 
			//string a=s.substr(0,i);
			//字符串转为整数
			int inta=parse(str,0,i); //atoi是一个函数 
			if(inta>=n)break;
			
			//插入除号
			for(int j=1;j<9-i-1;j++) {//加号、除号两个串之间的长度 
			string b=s.substr(i,j);
			string c=s.substr(i+j);//这是除号后面的串
			int intb=parse(str,i,j);
			int intc=parse(str,i+j,9-i-j);
		    if(intb%intc==0&&inta+intb/intc==n) ans++;	
		
			} 
		}
	}while(next_permutation(s.begin(),s.end()));
	printf("%d",ans);
	return 0;
} 

输入2013结果出错

10、连号区间数

#include<iostream>
#include<cstdio> 
using namespace std;
int n;//声明为全=全局变量可以自动初始化 
int arr[50000];
int ans;
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
	 scanf("%d",&arr[i]); 
	}
	for(int j=0;j<=n-1;j++){
		int max=arr[j+1];
		int min=arr[j];
		for(int i=j;i<=n-1;i++){
		if(arr[i]>max)max=arr[i];
		if(arr[i]<min)min=arr[i];

		if(i==j) ans++;
		else{
			if(max-min+1==i-j+1) ans++;//j-i形成连号区间 
		}
	
	}
	}
	printf("%d\n",ans); 
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值