【蓝桥杯真题】2016年省赛A组(C++)

        题目为本人学习、练习时写的,也参考了一些博客、网课(链接附在最后)。有些题目描述过于简便hhh~,也可以在网上搜索更详细的题目版本。

目录

题目1:猜年龄

题目2:吹蜡烛

题目3:填方格

题目4:快速排序

题目5:消除尾一

题目6:寒假作业

题目7:剪邮票

题目8:四平方和定理

题目9:密码脱落

题目10:

题目1:猜年龄

题目描述:“我的年龄是两位数,我比儿子大27岁,若把我的年龄位置交换,刚好为我儿子的年龄”,一共有多少种情况。

#include<iostream>

using namespace std;

int main(){
	int ans = 0;
	for(int i=28; i<100; i++){
		int a=0,b=0;
		b = i%10;
		a = i/10;
		if((a+10*b)==(i-27)){
			ans++;
		}
	}	
	cout << ans << endl;
	return 0;
}

题目2:吹蜡烛

题目描述:每年吹与年龄相同根数的蜡烛,从某年开始到现在一共236根,求开始过生日的年龄。

#include<iostream>

using namespace std;

int main(){
	for(int i=1; i<120; i++){
		int num=0;
		for(int j=i; j<120; j++){
			num += j;
			if(num==236){
				cout << i << " " << j;
				break;
			}	
		}
	}
	return 0;
}

题目3:填方格

题目描述:在下列格子填入0-9, 连续两个数字不能相邻,一共有多少种方案?

#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
int arr[10]={0,1,2,3,4,5,6,7,8,9};

bool check(){		
	if(abs(arr[0]-arr[1])==1||
	   abs(arr[0]-arr[3])==1||
	   abs(arr[0]-arr[4])==1||
	   abs(arr[0]-arr[5])==1||
	   
	   abs(arr[1]-arr[2])==1||
	   abs(arr[1]-arr[4])==1||
	   abs(arr[1]-arr[5])==1||
	   abs(arr[1]-arr[6])==1||
	   
	   abs(arr[2]-arr[5])==1||
	   abs(arr[2]-arr[6])==1||
	   
	   abs(arr[3]-arr[4])==1||
	   abs(arr[3]-arr[7])==1||
	   abs(arr[3]-arr[8])==1||
	   
	   abs(arr[4]-arr[5])==1||
	   abs(arr[4]-arr[7])==1||
	   abs(arr[4]-arr[8])==1||
	   abs(arr[4]-arr[9])==1||
	   
	   abs(arr[5]-arr[6])==1||
	   abs(arr[5]-arr[8])==1||
	   abs(arr[5]-arr[9])==1||
		
	   abs(arr[6]-arr[9])==1||
	   
	   abs(arr[7]-arr[8])==1||
	   abs(arr[8]-arr[9])==1) 
	   return false;

}


int main(){
	int ans = 0;
	do{
		if(check()){
			ans++;
		}
	}while(next_permutation(arr,arr+10));
	cout << ans << endl;
	return 0;
}

题目4:快速排序

题目描述:选一个标准,其左边元素不大于它,其右边元素不小于它。(代码填空)

#include<iostream>
using namespace std;


void swap(int a[], int p, int r){
	int t = a[p];
    a[p] = a[r];
    a[r] = t;
}

int partition(int a[], int p, int r){
	int i = p;
    int j = r+1;
    int x = a[p];
    while(1){
		while(i<r && a[++i] < x);
        while(a[--j] > x);
        if(i>=j) break;
        swap(a, i, j);
    }
    swap(a, p, j);//填空代码
    return j;
}

void quicksort(int a[], int p, int r){
	if(p<r){
		int q = partition(a, p, r);
        quicksort(a, p, q-1);
        quicksort(a, q+1, r);
    }
}

int main(){
	int i;
    int a[]= {13,12,2,6,8,10,9,3,4};
    int N = 9;
    quicksort(a, 0, N-1);
    
    for(int i=0; i<N; i++){
		cout << a[i] << " ";
    }
    cout << endl;
}
 

题目5:消除尾一

题目描述:把一个整数的二进制表示的最右边连续的1全部变成0,如果最后一位是0,则原数字保持不变。(代码填空)

#include<stdio.h>

void f(int x){
	int i;
	for(i=0; i<32; i++){
		printf("%d", (x>>(31-i))&1);//输出二进制数 
	}
	printf("   ");
	
	x = (x+1)&x;//填空  加一后 连续的一变成零 多出来一个一和原来的零与后还是零
	
	for(i=0; i<32; i++){
		printf("%d", (x>>(31-i))&1);
	}
	printf("\n");
}

int main(){
	
	f(103);
	f(12);
	return 0;
}

题目6:寒假作业

题目描述:在下列括号内填写1-13某个数字,但不能重复,一共有几种方案。(结果填空)

()+()=()

()-()=()

()×()=()

()÷()=()

#include<iostream>
int ans;
using namespace std;
int a[13]={1,2,3,4,5,6,7,8,9,10,11,12,13};
bool check(){
	if(a[0]+a[1]==a[2]&&
	   a[3]-a[4]==a[5]&&
	   a[6]*a[7]==a[8]&&
	   a[9]/a[10]==a[11]&&
	   a[9]%a[10]==0)
	   return true;
	return false;
}

void f(int k){//全排列
	if(k==13){
		if(check()){
			ans++;
		}
	}
	for(int i=k; i<13; i++){
		int t = a[i]; a[i] = a[k]; a[k] = t;
		if(k==2&&a[0]+a[1]!=a[2]){//提前检查 加快速度 
			t = a[i]; a[i] = a[k]; a[k] = t;
			continue;
		}
		f(k+1);
		t = a[i]; a[i] = a[k]; a[k] = t;
	}
}

int main(){
	f(0);
	cout << ans << endl;
}

题目7:剪邮票

题目描述:共12张中剪出5张,这5张需连通。一共有多少种不同的剪取方法。请填写表示方案数目的整数。

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int ans=0;
void dfs(int g[3][4], int x, int y){//连通检查
	g[x][y]=0;
	if(x-1>=0&&g[x-1][y]==1){
		dfs(g, x-1, y);	
	}
	if(x+1<=2&&g[x+1][y]==1){
		dfs(g, x+1, y);
	}
	if(y-1>=0&&g[x][y-1]==1){
		dfs(g, x, y-1);
	}
	if(y+1<=3&&g[x][y+1]==1){
		dfs(g, x, y+1);
	}
} 

bool check(int a[13])
{
	int g[3][4], count=0;
	for(int i=0; i<3; i++){
		for(int j=0; j<4; j++){
			if(a[i*4+j]==1){
				g[i][j] = 1;
			}else{
				g[i][j] = 0;
			}
			
		}
	}
	
	for(int i=0; i<3; i++){
		for(int j=0; j<4; j++){
			if(g[i][j]==1){
				dfs(g, i, j);
				count++;
			}
		}
	}
	
	if(count==1){//一次连通 搜索后 全为0
		return true;
	}
	else{
		return false;
	}
}

int main(){
	int a[]={0,0,0,0,0,0,0,1,1,1,1,1};
	do{
		if(check(a)){
			ans++;
		}
	}while(next_permutation(a,a+12));
	cout << ans << endl; 
	return 0;
}

题目8:四平方和定理

题目描述:四平方和定理又称为拉格朗日定理:每个正整数都可以表示为至多4个正整数的平方和。如果把0包括进去,就正好可以表示为4个数的平方和

#include<iostream>
#include<math.h>
using namespace std;
typedef long long int ll;
 
int main(){
	ll N;
	cin >> N;
	for(int i=0; i*i<N/4; i++){
		for(int j=i; i*i+j*j<N/2; j++){
			for(int k=j; i*i+j*j+k*k<3*N/4; k++){//简单枚举然后加速
				    int d = N-i*i-j*j-k*k;//只使用三层循环
				    d = sqrt(d);
				    if(i*i+j*j+k*k+d*d==N){
				    	if(d<k){
							break;
						}
						if(d!=N){
							cout << i << " " << j << " " << k << " " << d << endl;
							return 0;
						} 	
					}
			
				}
			}
		}
	return 0;
}

题目9:密码脱落

题目描述:X星球的考古学家发现了一批古代留下来的密码。 这些密码是由A、B、C、D 四种植物的种子串成的序列。 仔细分析发现,这些密码串当初应该是前后对称的(也就是镜像串)。 由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。

你的任务是: 给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。

输入一行,表示现在看到的密码串(长度不大于1000) 要求输出一个正整数,表示至少脱落了多少个种子。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char s1[1000];
int dp[1000][1000];
char s2[1000];

int lcs(const char *s1, const char *s2, int len){//求最大公共子串 	
	for(int i=1; i<=len; i++){
		for(int j=1; j<=len; j++){
			if(s2[j-1]==s1[i-1]){
				dp[i][j] = dp[i-1][j-1] + 1;
			}
			else{
				dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
			}
		}
	} 
	return dp[len][len];
}
int main(){
	cin >> s1;
	int len = strlen(s1);
	for(int i=0; i<len; i++){//翻转字符串 
		s2[i] = s1[len-i-1];
	}
	int l = lcs(s1, s2, len);
	cout << len - l << endl;
	return 0;
}

题目10:最大比例系数

题目描述:

X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。并且,相邻的两个级别间的比例是个固定值。也就是说:所有级别的奖金数构成了一个等比数列。比如:16,24,36,54.其等比值为:3/2。现在,我们随机调查了一些获奖者的奖金数。请你据此推算可能的最大的等比值。

输入第一行为数字 N (0<N<100),表示接下的一行包含N个正整数。 第二行N个正整数Xi(Xi<1 000 000 000 000),用空格分开。每个整数表示调查到的某人的奖金数额。

输出一个形如A/B的分数,要求A、B互质。表示可能的最大比例系数

测试数据:

①输入:3      1250 200 32

输出:25/4

②输入:4      3125 32 32 200

输出:5/2

③输入:3      549755813888 524288 2

输出:4/1

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
typedef long long int LL;
int N; 
LL data[100];
struct Ratio{//储存分数 
	LL x,y;
	Ratio (LL xx, LL yy){
		x = xx;
		y = yy;
	}
};
vector<Ratio> ratios;
map<LL, map<LL,LL> >all_ex;//ell_ex[x][pow] x开pow次方 
map<LL, map<LL,LL> >all_log;// ell_log[x][y] y的几次方为x 


void init(){
	for(int i=2; i<1e6; i++){//底数 
		LL cur = (LL)i*i;
		int pow=2;
		while(cur<1e12){
			all_ex[cur][pow] = i;
			all_log[cur][i] = pow;
			pow++;
			cur *= i; 
		}	
	}
}
 
LL gcd(LL x, LL y){
	if(y==0){
		return x;
	}	
	else{
		gcd(y, x%y);
	}
}

LL extract(LL x, LL pow){
	if(pow == 1){
		return x;
	} 
	if(x == 1){
		return 1;
	}
	if(all_ex[x].find(pow)!=all_ex[x].end()){//若可以对x开pow整数次方 
		return all_ex[x][pow]; 
	}else{
		return -1;
	}
} 

LL log(LL base, LL x){
	if(base==x){
		return 1;
	} 
	if(all_log[x].find(base)!=all_log[x].end()){//base的某次方为x 
		return all_log[x][base];
	}
	return -1;
}
int main(){
	init();//初始化两个map 
	cin >> N;
	for(int i=0; i<N; i++){//输入数据 
		cin >> data[i];
	}
	sort(data,data+N);//从小到大排序 
	if(N==1){
		return 0;
	}
	else if(N==2){//只有两项 直接输出二者约分后结果 
		LL g = gcd(data[1], data[0]);
		cout << data[1]/g << "/" << data[0]/g <<endl;
		return 0;
	}
	
	for(int i=1; i<N; i++){
		if(data[i]!=data[i-1]){//去重 
			LL g = gcd(data[i], data[i-1]);
			ratios.push_back(Ratio(data[i]/g,data[i-1]/g));//存入分数形式 
		}
	}
	
	for(int pow=1; pow<=40; pow++){//对第一个比值开1-pow次方,若该基数也是其他比值的基数,则该基数为答案。 
		Ratio r = ratios[0];
		LL x = r.x;
		LL y = r.y;
		LL base_x = extract(x, pow);//对x开pow次方,作为基数 
		LL base_y = extract(y, pow);
		if(base_x==-1||base_y==-1){//开不出 
		 	continue;
		} 
		bool all_match = true;
		for(int i=1; i<ratios.size(); i++){
			LL xx = ratios[i].x;
			LL yy = ratios[i].y;
			LL log_x = log(base_x, xx);//以base_x为底的多少次方 
			LL log_y = log(base_y, yy);
			if(base_y==1&&yy==1){
				log_y = log_x;
			} 
			if(log_x==-1||log_y==-1||log_x!=log_y){
				all_match = false;
				break;
			}
		} 
		if(all_match){
			LL g = gcd(base_x, base_y);
			cout << base_x/g << "/" << base_y/g << endl;
			return 0;
		}
		
	} 
	return 0;
}

参考资料:

蓝桥杯历年真题及详细解答_元气算法的博客-CSDN博客_蓝桥杯真题

【蓝桥杯】2013年-2018年蓝桥杯C/C++大学A组省赛真题_哔哩哔哩_bilibili

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值