蓝桥杯 省赛 研究生组
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,完结