蓝桥杯 一些练习


2023.1.14 unhappy

Day 1 修改数组 ⭐⭐

题目描述
给定一个长度为 N 的数组 A = [A1, A2, · · · AN ],数组中有可能有重复出现的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,··· ,AN。

当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则小明会给 Ai 加上 1 ;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1 ,直到 Ai 没有在 A1 ∼ Ai−1 中出现过。

当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。
现在给定初始的 A 数组,请你计算出最终的 A 数组。

输入格式
第一行包含一个整数 N。 第二行包含N个整数A1,A2,··· ,AN

输出格式
输出N个整数,依次是最终的A1,A2,··· ,AN。

样例输入
5
2 1 1 3 4

样例输出
2 1 3 4 5

评测用例规模与规定
对于 80% 的评测用例,1 ≤ N ≤ 10000。
对于所有评测用例,1 ≤ N ≤ 100000,1 ≤ Ai ≤ 1000000。

思路:暴力(模拟过程,好像是80分,第二种思路貌似对我来说有点难度略过~
注意:先写什么后写什么,怎么用代码实现~(哈哈哈有认真听课!

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+7;
int arr[N];

bool mark[N*10]; //标记数组,判断前面是否出现过 

int main(){
	int n;
	cin>>n;
	
	for(int i=0; i<n; i++){
		cin>>arr[i];
	}
	
	for(int i=0; i<n; i++){
		if(!mark[arr[i]]){  //没出现过
			mark[arr[i]] = 1; 
		}	
		else{   //该数已经出现过 
			while(mark[arr[i]]) arr[i]++;  //一直将arr[i]的值加1,直到mark的值为0 
			mark[arr[i]] = 1; 
		}
	}
	for(int i=0; i<n; i++){
		cout<<arr[i];
	} 
	return 0;
}

1、关键字 const:

定义:const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。
目的:const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。使用const在一定程度上可以提高程序的安全性和可靠性。
eg:
const int Max=100;
Max++; //会产生错误

2、定义bool型数组
定义数组 mark 时,放在主函数之外的话,自动初始化为全零的数组;若放在主函数里,mark数组里为随机值。

2023.1.15 angry…

2023.1.16 calm

Day 2 时间显示 ⭐

请添加图片描述
请添加图片描述
思路:不需要显示年月日,所以可以将之前的整数天去掉。
1 天 = mod = 86400000 ms
①对输入数据除 mod 取余得到第 n+1 天的毫秒数;

②除1000得到第 n+1 天的秒数 time;

③hour = time / 3600;
minute = time % 3600 / 60;
second = time % 3600 % 60 / 60

④在输出的时候,结果不到两位的需要在前面加 0 输出,要进行一下判断。

#include<bits/stdc++.h>
using namespace std;

const int mod = 86400000;

int main(){
	long long n;
	cin>>n;
	
	int time = n%mod;
	time = time / 1000;  //第n+1天的总秒数
	
	int hour = time / 3600;  //小时数 
	time = time % 3600;
	
	int minute = time / 60;  //分钟数 
	
	int second = time % 60;
	
	if(hour<10) cout<<0<<hour;
	else cout<<hour;
	cout<<":";
	
	if(minute<10) cout<<0<<minute;
	else cout<<minute;
	cout<<":";	
	 
	if(second<10) cout<<0<<second;
	else cout<<second;	
	 
	return 0;
} 

1、long long

int 型:32位整型,取值范围为-2^31 ~ (2^31 - 1) 。
long 型:在32位系统是32位整型,取值范围为-2^31 ~ (2^31 - 1);在64位系统是64位整型,取值范围为-2^63 ~ (2^63 - 1)
long long型:是64位的整型(8字节),取值范围为-2^63 ~ (2^63 - 1)。
请添加图片描述

题目所给时间不超过10^18,所以要用 long long 型

2、输出的时候,结果不到两位的需要在前面加 0 输出
代码如下:

if(hour<10) cout<<0<<hour;
	else cout<<hour;
	cout<<":";
	
	if(minute<10) cout<<0<<minute;
	else cout<<minute;
	cout<<":";	
	 
	if(second<10) cout<<0<<second;
	else cout<<second;

2023.1.17 happy

Day 3 异或数组 ⭐⭐⭐

请添加图片描述
请添加图片描述
在这里插入图片描述
思路:
① 按位异或,同为 1 ,不同为 0 ;

② 最终结果大的获胜:二进制数中,从高位比较,谁先单独有 1 ,说明谁大。(谁的 1 靠左先出现谁就大

③emm…小赵老师说…这个思路不好理解,就不让我理解了…
直接用代码实现:

相等的情况:
二进制所有位 1 的数目都是偶数
(所有数的第 i 位统计,按位求 1 的数目)

先手赢:
情况一:二进制最高位为 1 的数字个数为 1 个
情况二:数字总数为奇数个,二进制最高位为 1 的数字个数为奇数个
(先手拿到一个只有该数最高位为 1 的数,会赢

后手赢:
情况一:最高位为 1 的个数为奇数个,且总数个数为偶数。

最高位为 1 的个数为偶数时,比较次高位。

代码实现如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 2e5+7;

int array[N];  //用来保存数 
int arr[N][21];  //用来保存数的二进制(最高20位,0-20)

//获取所有数的二进制位,存入数组
void fun(int i){     
	int x = array[i];
	int pos = 0;
	while(x){
		arr[i][pos++] = x&1;
		x = x>>1;
	}
} 


int main(){
	int T;
	cin>>T;
	while(T--){    //将数读入数组中 
		int n;
		cin>>n;
		
		//memset(arr,0,sizeof arr);  //将数组的数全部赋值为 0 ,但复杂度较高 
		
		for(int i=0; i<n; i++){ //输入各数 
			cin>>array[i]; 
			
			for(int j=0; j<=20; j++) arr[i][j]=0;   //将数组初始化,手动赋0 
			
			fun(i);
		}
		
		int pos = -1;
		bool check = 0;
		
		//寻找“最高位”,对第i位上1的数目进行检查
		for(int i=20; i>=0; i--){    
			
			int cnt = 0;
			for(int j=0; j<n; j++){    //统计某位上所有数中1的个数 
				if(arr[j][i]==1){
					cnt++; 
				}
			} 
			
			if(cnt&1){    //判断,如果某位上二进制为奇数个,即为“最高位” 
				if(cnt==1) check=1;  //先手赢的第一种情况 
				pos = i;
				break;  //找到“最高位”,跳出循环 
			} 
			 
		} 
		
		if(pos==-1) cout<<0<<endl;
		else{
			if(check || n%2) cout<<1<<endl;   //先手赢 
			else cout<<-1<<endl;
		} 	
	}
	return 0;
}

1、任何数和 1 进行 & 运算

得到该数的二进制形式的最低位

arr[i][pos++] = x&1;

2、二进制数的右移

依次右移一位,循环保存各位二进制数。

arr[i][pos++] = x&1;
			x = x>>1; //右移一位

保存时,从右向左保存,数组位置 0 保存最低位

3、memset()
对数组里的数初始化为某一特定值。复杂度较高,没用。

2023.1.18 intricate

Day 4 重复字符串 ⭐⭐⭐?

请添加图片描述请添加图片描述
请添加图片描述

分析:
首先字符串内字符个数要能整除K;
统计划分K部分后,各位上个出现的最多的 字符。少数服从多数

代码如下:
emm…有点问题,但是明明都一样呀…

#include<bits/stdc++.h>
using namespace std;

//const int N = 1e5+7;
//string arr[N];
vector<string>ve;
//map<char,int>mp;   //字典 
int mp[30];

int main(){
	int n;
	cin>>n;
	
	string s;
	cin>>s;
	
	int len = s.size();
	if(len%n != 0){   //不能进行划分的情况,无解 
		cout<<-1<<endl;
		return 0;
	}
	
	int m = len/n;  //表示循化节的长度 (每m个字符串保存一下) 
	int pos = 0; 
	string now = "";   //临时变量 ,初始字符串 
	
	for(int i=0; i<len; i++){   //遍历字符串 
		now+=s[i]; 
		if(now.size()==m){  //当前获得一个循环节 
			ve.push_back(now);   //放进去(在尾部加入一个循环节now) 
		//	cout<<now<<endl; 
			now = "";    //放入后清空一下 
		}
	}
	int ans = 0;
	for(int i=0; i<m; i++){     //遍历循环节 
		int mx = 0;
		char mxchar;
		for(int k=0; k<ve.size(); k++){
			mp[ve[k][i]-'a']++;   //统计出现次数 
		//	cout<<mp[ve[k][i] - 'a']<<endl;
			if(mp[ve[k][i]]-'a'> mx){
				mx = mp[ve[k][i]-'a'];
				mxchar = ve[k][i];
				}
			}
		cout<<mxchar<<endl;
		for(char j='a'; j<='z'; j++){
			if(j==mxchar) continue;
			ans += mp[j-'a'];   //mp[j]表示字符 j 出现的次数 
		}
		//mp.clear();   //清空map中的所有元素 
		memset(mp, 0, sizeof mp);
	}
	cout<<ans<<endl;
	return 0;
} 

string
字符串可以用 string 类型来保存

C风格字符串(以空字符结尾的字符数组)太过复杂难于掌握,不适合大程序的开发,所以C++标准库定义了一种string类

vector
vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。

vector< string>是字符串容器
eg:vector<string> s[2]
这句话的意思就是定义了一个字符串容器,里面可以存放2个字符串。(存放string类型的数组)
而string只是定义一个字符串。

函数实现功能:

ve.clear()             清空容器中所有数据。
ve.empty()             判断容器是否为空。
ve.erase(pos)          删除pos位置的数据
ve.erase(beg,end)      删除[beg,end)区间的数据
ve.front()             传回第一个数据。
ve.back()              传回最后一个数据,不检查这个数据是否存在
ve.insert(pos,elem)    在pos位置插入一个elem拷贝
ve.pop_back()          删除最后一个数据。
ve.push_back(elem)     在尾部加入一个数据。
ve.resize(num)         重新设置该容器的大小
ve.size()              回容器中实际数据的个数。
ve.begin()             返回指向容器第一个元素的迭代器
ve.end()               返回指向容器最后一个元素的迭代器
ve.reserve()           改变当前vecotr所分配空间的大小
ve.capacity()          容器容量
ve.at(idx)             传回索引idx所指的数据,如果idx越界,抛出out_of_range
ve.assign(beg,end):    将[beg; end)区间中的数据赋值给ve
ve.assign(n,elem):     将n个elem的拷贝赋值给ve
ve.~ vector <Elem>()    销毁所有数据,释放内存

map 字典
map 是一种特殊的数据结构:一种元素对(pair)的无序集合,pair 的一个元素是 key,对应的另一个元素是 value,所以这个结构也称为关联数组或字典。这是一种快速寻找值的理想结构:给定 key,对应的 value 可以迅速定位。
map 这种数据结构在其他编程语言中也称为字典(Python)、hash 和 HashTable 等。

(1)find()
find(key)返回键为key的映射的迭代器,时间复杂度为N(logN),N为map中映射的个数。

(2)erase()
erase有两种用法:

① 删除单个元素,删除一个区间内的所有元素。
删除单个元素的方法==》mp.erase(it),it为删除的元素的迭代器,时间复杂度为O(1)。

mp.erase(key),key为欲删除的键。时间复杂度为O(logN),N为map内元素的个数。

② 删除一个区间内的所有元素。
mp.erase(firse,last)删除[first,last).

时间复杂度O(last-first)

(3)size()
size()用来获得map中映射的对数,时间复杂度为O(1)。

(4)clear()
clear()用来清空map中的所有元素,复杂度为O(N),其中N为map中的元素的个数。

2023.1.19

Day 5 回文日期 ⭐⭐⭐

请添加图片描述
请添加图片描述
思路:
①年份确定后,月日就可以确定
②月份不同,判断每月天数不同
③设置两个判断函数,判断是否符合要求

代码如下(90分代码):

#include<bits/stdc++.h>
using namespace std;

int leap_month[10];    //定义一个数组保存 31天的月份 

bool judge(int year,int day,int month){  //判断是否符合日期 
	if(day==0 || day>31) return 0;
	if(month==0 || month>12) return 0;
	
	for(int i=0; i<7; i++){
		if(leap_month[i]==month){
			if(day>31) return 0;  /
			else return 1;
		}
	}
	
	if(month==2){
		if((year%4==0&&year%100!=0) || (year%400==0)){   //闰年的判断 
			if(day>29) return 0;  
			else return 1; 
		}
		else{    //不是闰年 
			if(day>28) return 0;
			else return 1; 
		}
	}
	
	if(day>30) return 0;
	return 1;
}

bool check1(int year){
	int D = year % 10;
	year /= 10;
	int C = year % 10;
	year /= 10;
	int B = year % 10;
	year /= 10;
	int A = year % 10;
	year /= 10;
	int day = B*10+A;
	int month = D*10+C;
	return judge(year,day,month);
}

bool check2(int year){
	int B = year%10;
	year/=10;
	int A = year%10;   ///
	year/=10;
	if(year%10!=B || year/10!=A) return 0;
	
	int day = B*10+A;
	int month = day;
	return judge(year,day,month); 
}



int main(){
	//初始化数组 
	leap_month[0] = 1;
	leap_month[1] = 3;
	leap_month[2] = 5;
	leap_month[3] = 7;
	leap_month[4] = 8;
	leap_month[5] = 10;
	leap_month[6] = 12;
	
	int n;
	cin>>n;
	
	int year = n / 10000;
	int year1 = year + 1;
	int year2 = year1 + 1;
	while(!check1(year1)){
		year1++;
	}
	
	while(!check2(year2)){
		year2++;
	}
	
//	cout<<year1<<"-----"<<year2<<endl;

	int y1 = year1;
	int y2 = year2;
	
	int D = year1 % 10;
	year1 /= 10;
	int C = year1 % 10;
	year1 /= 10;
	int B = year1 % 10;
	year1 /= 10;
	int A = year1 % 10;
	year1 /= 10;
	int day = B*10+A;
	int month = D*10+C;
	
	cout<<y1;
	if(month<10) cout<<0<<month;
	else cout<<month;
	if(day<10) cout<<0<<day<<endl;
	else cout<<day<<endl;
	
	B = year2%10;
	year2/=10;
	A = year2%10;   ///
	year2/=10;
	if(year2%10!=B || year2/10!=A) return 0;
	day = B*10+A;
	month = day;
	
	cout<<y2;
	if(month<10) cout<<0<<month;
	else cout<<month;
	if(day<10) cout<<0<<day<<endl;
    else cout<<day<<endl;
    
    return 0;
}

1、判断闰年

“ 四年一闰;百年不闰,四百年再闰。”

(year%4==0&&year%100!=0) || (year%400==0)

2、
定义一个数组保存 31天的月份
leap_month[10];

2023.1.23 大年初二~

Day 6 蓝肽子序列

请添加图片描述请添加图片描述
请添加图片描述
思路:
字符串:首先只保存首个字母,形成新的字符串,重新排序,再利用字典进行映射
数组表示:

0123456789
LanQiaoBei             LanQiao
 1   2  3
LanTaiXiaoQiao        LanQiao
  1  4  5  2

012
LQB  mp[0]=0      映射得到相应蓝钛所在位置
     mp[1]=3

0123
LTXQ

 

代码如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 1e3+7;

map<string, int>mp;   //哈希表作用,记录某个字符串有没有出现过 
int arr1[N];
int arr2[N];
int dp[N][N];


int main(){
	string s1,s2;
	cin>>s1>>s2;
	string now;
	int cnt = 1;   //当前蓝肽的种类数 
	int pos1 = 1;
	// LanQiaoBei  处理第一个字符串 
	for(int i=0; i<s1.size(); i++){    //找到蓝肽 
		if(s1[i]<='Z'){
			if(i!=0){
				if(mp[now]==0){   //该蓝肽第一次出现,分配一个新的 (map初始值都是0 
					 mp[now] = cnt++; 
				} 
				arr1[pos1++] = mp[now];  //arr[1]=1;  arr[2]=2;  arr[3]=3;  
			} 
			now = "";
			now = now + s1[i];
		}  //now = Lan
		else now = now + s1[i];
	}
	
	if(mp[now]==0){
		mp[now] = cnt++;
	}
	arr1[pos1++] = mp[now];
	now = "";
	
	// LanQiaoBei  处理第二个字符串
	int pos2 = 1; 
	for(int i=0; i<s2.size(); i++){    //找到蓝肽 
		if(s2[i]<='Z'){
			if(i!=0){
				if(mp[now]==0){   //该蓝肽第一次出现,分配一个新的 (map初始值都是0 
					 mp[now] = cnt++; 
				} 
				arr2[pos2++] = mp[now];  //arr[1]=1;  arr[2]=4;  arr[3]=5;  arr[4]=2
			} 
			now = "";
			now = now + s2[i];
		}  //now = Lan
		else now = now + s2[i];
	}
	
	if(mp[now]==0){
		mp[now] = cnt++;
	}
	arr2[pos2++] = mp[now];
	
	for(int i=1; i<pos1; i++){
		for(int j=1; j<pos2; j++){
			if(arr1[i]==arr2[j]){
				dp[i][j] = dp[i-1][j-1] + 1;
			}
			dp[i][j] = max(dp[i][j],max(dp[i-1][j],dp[i][j-1]));
		}
	} 
	cout<<dp[pos1-1][pos2-1]<<endl;
	
	return 0;
} 

1、dp问题 动态规划

模板:

	for(int i=1; i<pos1; i++){
		for(int j=1; j<pos2; j++){
			if(arr1[i]==arr2[j]){
				dp[i][j] = dp[i-1][j-1] + 1;
			}
			dp[i][j] = max(dp[i][j],max(dp[i-1][j],dp[i][j-1]));
		}
	}

emm…有点懵逼…字典到底是啥呀!!

最长公共子序列问题
子序列:相对位置不变,可以去掉其中的部分字母

2023.1.25 初四

Day 7 大胖子走迷宫

请添加图片描述

请添加图片描述
请添加图片描述
思路:
走迷宫问题
BFS 广度优先搜索

(cnt,x,y)

//没有任何限制条件 
(cnt+1,x,y)
//前提:5*5和3*3的区域内不能有障碍物 
(cnt+1,x+1,y)
(cnt+1,x,y+1)
(cnt+1,x-1,y)
(cnt+1,x,y-1)

1、四舍五入

法一 对指定位进行四舍五入:

#include<bits/stdc++.h>
using namespace std;

int main(){
	double x = 1.52353;
	double y = x * 1000;
	// C++里保留n位小数很繁琐,用C 
	printf("%.3f", floor(y+0.5)/1000);  //保留3位小数 
	
	return 0;
}

法二:
①floor:只保留整数,相当于强制类型转换,转换整型
②ceil:保留整数,若有小数部分,则整数 + 1

#include<bits/stdc++.h>
using namespace std;

int main(){
	double x = 0.503;
	double y = 0.425;
	cout<<floor(x+0.5)<<"---"<<floor(y+0.5)<<"----"<<ceil(x-0.5)<<"---"<<ceil(y-0.5)<<endl;
	return 0;
}

监督小赵老师学习!(其实在监督我学习哈哈哈)希望小赵老师能拿个奖呀~
本白中白跟着听一听(更新到小赵老师比赛吧,也不知道啥时候比赛
累了…不想听了
second,完结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值