蓝桥杯题库刷题

蓝桥杯题库刷题

一.入门篇

二.基础篇

10.十进制转十六进制

(1)题目

在这里插入图片描述

(2)代码
方法一:暴力法
#include<iostream>
#include<stdlib.h>
using namespace std;
// 方法一:暴力法 
int a;
int A[20];

char change (int m) {
	switch(m) {
			case 0:return '0'; break;
			case 1:return '1'; break;
			case 2:return '2'; break;
			case 3:return '3'; break;
			case 4:return '4'; break;
			case 5:return '5'; break;
			case 6:return '6'; break;
			case 7:return '7'; break;
			case 8:return '8'; break;
			case 9:return '9'; break;
			case 10:return 'A'; break;
			case 11:return 'B'; break;
			case 12:return 'C'; break;
			case 13:return 'D'; break;
			case 14:return 'E'; break;
			case 15:return 'F'; break;
		}	
}

int main() {
	scanf("%d",&a);
	if(a < 0 || a > 2147483647) return -1;
	int t = 0;
	if(a == 0)
	{
		printf("0");
	}  // 0不能作被除数,所以如果输入0,则直接输出0
	
		while(a) {
			A[t++] = a % 16;  
	 		a /= 16;	 
		}
		for(int i = t - 1 ; i >= 0; i -- ) {
			putchar(change(A[i])); // 将其他类型转换为char型 
		}
	return 0;
}
方法二:利用ASCII码表大小字母转换法

核心代码

	if(m > 9) str[k ++ ] = 'A' + m - 10;
		else str[k ++ ] = '0' + m; 

具体代码

#include<iostream>
#include<stdlib.h>
using namespace std;
// 方法二:简便法
typedef long long LL;
LL count;
char str[100];
int k = 0;

int main() {
	scanf("%d",&count);
	if(count == 0) printf("0");
	while(count > 0) {
		int m = count % 16;
		count /= 16;
		if(m > 9) str[k ++ ] = 'A' + m - 10;
		else str[k ++ ] = '0' + m; 
	}
	for(int  i = k - 1; i >= 0; i -- ) printf("%c",str[i]);
	return 0 ; 
	
} 

11.十六进制转十进制

(1)题目

在这里插入图片描述

(2) 代码
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;

string str;

int main() {
	
	cin >> str;
	int length = str.length() ;
	LL num = 0;
	LL r = 1;
	for(int i = length - 1; i >= 0; i --) {
		if(str[i] >= '0' && str[i] <= '9') {
			num += (str[i] - '0') * r; 
			r *= 16;
			}
		else {
			num += (str[i] - 'A' + 10) * r;
			r *= 16;
		}
			
	}
	cout<< num;
	
	
	return 0;
}
 

🔺12. 十六进制转八进制

(1)题目

在这里插入图片描述

(2)代码

思路
整体思路:先将16进制转换为二进制,再把二进制转换为8进制
注意:因为最后一个测试数据非常大 并且方便 前导0的去除,用c++string比较方便

#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;

/* 整体思路:先将16进制转换为二进制,再把二进制转换为8进制 */
/* 注意:因为最后一个测试数据非常大 + 前导0的去除,用c++string比较方便*/ 

int main(){
	int n; // 行数 
	cin>>n;
	if(n < 1 || n > 10) return -1; 
	string hexadecimal, // 16进制 
	binary, // 二进制 
	octal; // 八进制 
	
	for(int i = 0; i < n; i++){
		binary = "";
		octal = "";
		cin >> hexadecimal;
		if(hexadecimal.length() > 100000) return -1;
		/* 把16进制转换为二进制 */ 
		/* 思路:先把16进制字符串全部转换成对应二进制字符串,输入一个转换一个 */ 
		for(int j = 0; j < hexadecimal.size(); j++){
			switch(hexadecimal[j]){
				case '0' : binary += "0000"; break;
                case '1' : binary += "0001"; break;
                case '2' : binary += "0010"; break;
                case '3' : binary += "0011"; break;
                case '4' : binary += "0100"; break;
                case '5' : binary += "0101"; break;
                case '6' : binary += "0110"; break;
                case '7' : binary += "0111"; break;
                case '8' : binary += "1000"; break;
                case '9' : binary += "1001"; break;
                case 'A' : binary += "1010"; break;
                case 'B' : binary += "1011"; break;
                case 'C' : binary += "1100"; break;
                case 'D' : binary += "1101"; break;
                case 'E' : binary += "1110"; break;
                case 'F' : binary += "1111"; break; 
			}
		}
		/* 16进制转换成2进制后填0 */ 
		int binary_length = binary.size();
		// 差2位补2个0 
		if(binary_length % 3 == 1){
			binary = "00" + binary;
			binary_length += 2;
		}
		// 差1位补1个0 
		if(binary_length % 3 == 2){
			binary = "0" + binary;
			binary_length++;
		}
		// 将二进制转换为8进制 
		for(int k = 0; k < binary_length; k += 3) {
			int o = 4 * (binary[k] - '0') + 2 * (binary[k + 1] - '0') + (binary[k + 2] - '0');
			octal += (o + '0');
		}
		// 去除前导0 
		int p = 0;
		while(octal[p] == '0') p++;
		// 输出 
		for(; p < octal.size(); p++) cout << octal[p];
		cout << endl;
	}			
	return 0;
} 

13.数列排序

(1)题目

在这里插入图片描述

(2)代码

方法一:c++sort排序

#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<cmath>
#include<math.h>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10;
int n;
int a[N],temp[N];

int main() {
	scanf("%d",&n);
	if(n < 1 || n > 200) return -1;
	for(int i = 0; i < n ; i ++ ) {
		scanf("%d",&a[i]);
		if(fabs(a[i] > N)) return -1;
	}
	sort(a,0,n - 1);
	for(int i = 0; i < n; i++) {
        printf("%d ",a[i]);
    }
	return 0;
}

方法二:归并排序(O(nlogn))
归并排序模板

const int N = 1e6 + 10;

int n;
int q[N], temp[N];

// 归并排序
void merge_sort(int q[],int l,int r) {
    if(l >= r) return;
    int mid = l + r >> 1; // >>相当于/2
    merge_sort(q,l,mid),merge_sort(q,mid + 1, r); //递归排序,分别递归左右边
    int k = 0,i = l,j = mid + 1;
    // 归并
    
    while(i <= mid && j <= r) { // 先在中点两边分别比较并升序
        if(q[i] <= q[j]) temp[k++] = q[i++];
        else temp[k++] = q[j++];
    }
    // 防止一边已经排序完成,另一边还没排序完,所以把另一边继续排序
    while(i <= mid) temp[k++] = q[i++];
    while(j <= r) temp[k++] = q[j++];
    // 将排好序的值再赋给q[]
    for(i = l, j = 0; i <= r; i++,j++) q[i] = temp[j];
    
}

具体代码

#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<cmath>
#include<math.h>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10;
int n;
int a[N],temp[N];

// 归并排序

void merge_sort(int q[],int low,int high) {
	if(low >= high) return;
	int mid = (low + high) / 2;
	merge_sort(q,low,mid),merge_sort(q,mid + 1,high);
	int k = 0, i = low, j = mid + 1;
	while(i <= mid && j <= high) {
		if(q[i] < q[j]) temp[k ++ ] = q[i ++ ];
		else temp[k ++ ] = q[j ++ ]; 
	}
	while(i <= mid) temp[k ++ ] = q[i ++ ];
	while(j <= high) temp[k ++ ] = q[j ++ ];
	for(i = low,j = 0; i <= high; i ++, j ++ ) q[i] = temp[j];
		
}

int main() {
	scanf("%d",&n);
	if(n < 1 || n > 200) return -1;
	for(int i = 0; i < n ; i ++ ) {
		scanf("%d",&a[i]);
		if(fabs(a[i] > N)) return -1;
	}
	merge_sort(a,0,n - 1);
	for(int i = 0; i < n; i++) {
        printf("%d ",a[i]);
    }
	return 0;
}

方法三:快速排序(超时但是不知道原因,按理说快排和归并同样时间复杂度,希望有大佬看见回答下)
快速排序模板

const int N = 1e6 + 10;

int n;
int q[N];

// 快速排序
void quick_sort(int q[],int l,int r) {
    if(l >= r) return; // 判边界只有一个数时返回空
    int x = q[l + r >> 1], i = l - 1, j = r + 1; // 取分界点x,两头指针i,j
    while(i < j) { // 循环迭代,只要i,j未相遇,i往右走,j往左走
        do i++; while(q[i] < x);
        do j--; while(q[j] > x);
        if(i < j)  swap(q[i],q[j]);
        // 若所用语言没有swap
        // {
        //     int t = q[i];
        //     q[i] = q[j];
        //     q[j] = t;
        // }
        
    }
    /*这种情况只能int x = q[l]去左边界,若int x = q[r]取右边界也会造成无限递归死循环
    */
    quick_sort(q,l,j); // 左边界排序
    quick_sort(q,j + 1,r); // 右边界排序
    /*此处换成i也可以,但要注意对称
    且上面int x = q[l]处要改为int x = q[(l + r +1) / 2]
    (原因是若保持int x = q[l]会造成无限递归死循环)
    quick_sort(q,l,i - 1); // 左边界排序
    quick_sort(q,i,r); // 右边界排序
    */
}

具体代码

#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<cmath>
#include<math.h>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10;
int n;
int a[N],temp[N];

// 快速排序 
void quick_sort(int q[],int low,int high) {
	if(low >= high) return;
	int mid = q[low + high >> 1], i = low - 1, j = high + 1;
	while(i < j) {
		do i ++ ; while(q[i] < mid);
		do j -- ; while(q[j] > mid);
		if(i < j) {
			int temp = q[i];
			q[i] = q[j];
			q[j] = temp;
		}
	} 
	quick_sort(q,low,j);
	quick_sort(q,j,high);
}


int main() {
	scanf("%d",&n);
	if(n < 1 || n > 200) return -1;
	for(int i = 0; i < n ; i ++ ) {
		scanf("%d",&a[i]);
		if(fabs(a[i] > N)) return -1;
	}
	
	quick_sort(a,0,n - 1); // 快速排序
	
	for(int i = 0; i < n; i++) {
        printf("%d ",a[i]);
    }
	return 0;
}

14.时间转换

(1)题目

在这里插入图片描述

(2)代码
#include<iostream>
using namespace std;
typedef long long LL;

const int N = 1e6 + 10;
LL n;

int main() {
	scanf("%d",&n);
	int hours = n / 3600;
	int minutes = n % 3600 / 60;
	int seconds = n % 60;
	cout << hours << ":" << minutes << ":" << seconds;
	return 0;
} 

15.字符串对比

(1)题目

在这里插入图片描述

(2)代码

知识点1:string类型可以直接比较是否相等

if(str1 == str2) cout<< "2";

知识点2:string.end(),string.begin()函数

 begin()函数,返回一个迭代器,指向字符串的第一个元素。
 end()函数,也是返回一个迭代器,指向字符串末尾(最后一个字符的后一个位置)。
 迭代器本质为指针,但如果要取元素,必须加*去元素 
 --------------------------------------------------------------------------
	string str = "What";
	cout << "str.begin(): " << *(str.begin()) << endl;
	cout << "str.end(): " << *(str.end()-1) <<endl;
---------------------------------------------------------------------------				
	str.begin(): W
	str.end(): t

知识点3:string类型字符串转换大小写方法

	// 注意:头文件#include<algorithm>
	string src = "Hello World!";
    string dst;
	// 转换大写 
    transform(src.begin(), src.end(), back_inserter(dst), ::toupper);
    cout << dst << endl;
	// 转换小写 
    transform(src.begin(), src.end(), dst.begin(), ::tolower);
    cout << dst << endl;

知识点4:普通字符/字符数组转换方法

char change(char a[]) {
for(int i = 0; a[i] != '\0'; i ++ ) {
		// 转换大写 
		if(a[i] >= 'a' && a[i] <= 'z'){  //判断是否在小写字母范围内
			a[i] -= 32;
		}
		// 转换小写 
		if(a[i] >= 'A' && a[i] <= 'Z') {
			a[i] += 32; 
		} 
		puts(a); 
	}
}

具体代码

#include<iostream>
#include<cstring>
#include<string.h>
#include<ctype.h>
#include<bits/stdc++.h>
#include<algorithm> 
using namespace std;
typedef long long LL;

string str1;
string str2;
int i = 0;
int flag = 0;


int main() {
	ios::sync_with_stdio(false); // 让cin尽量变得和scanf()一样快,但还是会比scanf()慢点
	cin >> str1;
	cin >> str2;
	// 第一种情况 
	if(str1.length() != str2.length()) cout << "1";
	else { 
			// 第二种情况
			/* 知识点:string类型可以直接比较是否相等 */ 
			if(str1 == str2) cout<< "2";
			//  方法二:也可逐个比较字符串内的每个字符 
			/*
			while(str1[i] == str2[i]) {
				i ++ ;
				if(*(str1.end() - 1) && *(str2.end() - 1)) flag = 1;
			} 
			if(flag)  cout << "2";
			flag = 0;
			*/
			else {
				string str11;  
				string str22;  
				// string类型转换大写方法 
				transform(str1.begin(), str1.end(), back_inserter(str11), ::toupper);
				transform(str2.begin(), str2.end(), back_inserter(str22), ::toupper);
				// 第三种情况 
				if(str11 == str22) {
					cout << "3";
				}
				// 第四种情况 
				else cout << "4"; 	
		}	
	} 
	return 0;
}

16.分解质因数

(1)题目

在这里插入图片描述

(2)代码
#include<iostream>
#include<cstring>
#include<string.h>
#include<ctype.h>
#include<bits/stdc++.h>
#include<algorithm> 
using namespace std;
typedef long long LL;

int a,b;


// 分解质因数模板 
// 暴力做法 
void divide(int n)  {
	for(int i = 2; i <= n; i ++ ) {
		// 判断当前i(质因子)能否多次出现
		while(n != i) {
			if(n % i == 0) {
				cout << i << "*";
				n /= i;
			}
			else break;
		}
	}
	cout << n << endl;
}



int main () {
	scanf("%d%d",&a,&b); 
	for(int i = a; i <= b; i ++ ) {
		cout << i << "=";
		divide(i);
	}
	return 0;
}

17.矩阵乘法

(1)题目

在这里插入图片描述

(2)代码

知识点:矩阵乘法运算律

	c[i][j] += b[i][k] * a[k][j]; // 矩阵乘法运算法则,b[i][j]代表着上一次的高次幂 
#include<iostream>
using namespace std;

int a[30][30],b[30][30],c[30][30];
int n,m;


int main() {
	scanf("%d%d",&n,&m);
	for(int i = 0; i < n; i ++ ) {
		for(int j = 0; j < n; j ++ ) {
			cin >> a[i][j];
			b[i][j] = a[i][j];
			c[i][j] = 0;
		}	
	}
	if(m == 0) {
		for(int i = 0; i < n; i ++ ) {
			for(int j = 0; j < n; j ++ )
				if(i == j)	b[i][j] = 1;
				else b[i][j] = 0;
		}	
	}
	if(m > 0) {
		while(-- m ) { // 必须 -- m 
			for(int i = 0; i < n; i ++ ) {
				for(int j = 0; j < n; j ++ )
					for(int k = 0; k < n; k ++ )
						c[i][j] += b[i][k] * a[k][j]; // 矩阵乘法运算法则,b[i][j]代表着上一次的高次幂 
			}
			for(int i = 0; i < n; i ++ ) {
				for(int j = 0; j < n; j ++ ) {
					b[i][j] = c[i][j]; // 把这次运算结果给b,当作下一次高次幂的条件 
					c[i][j] = 0; // c存放运算结果,每次赋值完都要清空 
				}	
			}	
		}	
	}
	
	
	for(int i = 0; i < n; i ++ ) {
		for(int j = 0; j < n; j ++ )
			cout << b[i][j] << " ";
			cout << endl;
	}
	
	return 0;
}

18.矩阵面积交

(1)题目

在这里插入图片描述

(2)代码
#include<iostream>
using namespace std;

double x1,x2,y1,y2,x3,x4,y3,y4;
double s;

double min(double a, double b) {
	return a < b ? a : b;
}
double max(double a, double b) {
	return a > b ? a : b;
}

int main() {
	 ios::sync_with_stdio(false);
	 cin >> x1 >> y1 >> x2 >> y2;
	 cin >> x3 >> y3 >> x4 >> y4;
	 
	double xmax = min(max(x1,x2),max(x3,x4));
	double xmin = max(min(x1,x2),min(x3,x4));
	double ymax = min(max(y1,y2),max(y3,y4));
	double ymin = max(min(y1,y2),min(y3,y4));
	if(xmax > xmin && ymax > ymin)
		s = (xmax - xmin) * (ymax - ymin);
	
	
	printf("%.2lf",s);
	
	return 0;
} 

19.完美的代价

(1)题目

在这里插入图片描述

(2)代码
题目解析:
(1)Impossible 的两种情况:
	n为奇数时,如果已经有一个字符出现的次数为奇数,还找到了一个字符出现的次数为奇数,那么就不能构成回文串;
	n为偶数时,只要找到有一个字符出现的次数为奇数,那么就不能构成回文串。
 (2)题目中要求输出最小的交换次数,那么怎样才能保证交换次数最小呢?
  如果 n 为偶数,那么从第一字符开始,从后往前找第一个和它相同的字符,如果找了,就将找到的字符交换到最后一个位置,在下一次遍历时,就可以不用管刚才已经交换好的那来两个字符;下一次从第二个字符开始,从倒数第二个字符开始遍历,执行和上述相同的操作;
  如果 n 为奇数,在字符串的某一个位置找到了那个出现次数为奇数的字符,我们不必将次字符现在就交换到中间位置,而是先计算它到中间位置需要交换的次数,然后累加到 cnt 中,将剩下的字符都交换到对称后,再交换这个字符即可。
  试着想一想,如果第一个字符就为出现次数为奇数的字符,那么将它交换到中间位置,接下来交换其他字符时,每次的交换次数都会多一次。这其实是一种普遍的规律。
#include<iostream>
using namespace std;

int n;
string s;
	
int main () {

	cin >> n;
	cin >> s;
	int end = n - 1;  // 字符串最后一个字符 
	int count = 0; // 交换次数 
	int oddNum = 0; // 判断是否已经有一个单独的奇个数的字符了
	/*如果 n 为偶数,那么从第一字符开始,从后往前找第一个和它相同的字符,
	如果找了,就将找到的字符交换到最后一个位置,在下一次遍历时,就可以不用管刚才已经交换好的那来两个字符;
	下一次从第二个字符开始,从倒数第二个字符开始遍历,执行和上述相同的操作;*/
	for(int i = 0; i < end; i ++ ) { // 从第一个字符到倒数第二个字符遍历 
		for(int j = end; j >= i; j -- ) { // 从最后一个开始,到第i个字符,寻找与s[i]相同的字符
			if(i == j) {
				// n为偶数时,只要找到有一个字符出现的次数为奇数,那么就不能构成回文串。
				// n为奇数时,如果已经有一个字符出现的次数为奇数,还找到了一个字符出现的次数为奇数,那么就不能构成回文串;
				if(n % 2 == 0 || oddNum == 1) { 
					cout << "Impossible";
					return 0;
				}
				/*
				如果 n 为奇数,在字符串的某一个位置找到了那个出现次数为奇数的字符,
				我们不必将次字符现在就交换到中间位置,而是先计算它到中间位置需要交换的次数,
				然后累加到 cnt 中,将剩下的字符都交换到对称后,再交换这个字符即可。
				*/				
				oddNum = 1; // 找到一个字符出现的次数为奇数
				count += n / 2 - i; // 将次字符交换到中间位置的次数
			}
			else if(s[i] == s[j]) { // 如果找到了,将s[j]交换到s[end]位置
				for(int k = j; k < end; k ++ ) { // 交换相邻两个位置的字符 
					swap(s[k],s[k + 1]);
					count ++;
				}
				end -- ; // 末尾递减
				break; // 开始从i+1处重复操作 
			}	
		}		
	} 
	cout << count;
	return 0;
} 

(1)题目
(2)代码

(1)题目
(2)代码

(1)题目
(2)代码

(1)题目
(2)代码

(1)题目
(2)代码

(1)题目
(2)代码

(1)题目
(2)代码
  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值