蓝桥杯省赛备战笔记——(一)基础 + 字符串和日期
视频在B站被和谐了。。。。幸好提前下载了。。。。有需要的可以私信我
【晚一阵子吧,疫情还比较严重,道全封了,还在农村,没有网】
一、基础部分杂记
在竞赛中,我们认为计算机一秒能执行 5 * 10 ^ 8 次计算,如果题目给出的时间限制是 1 s ,那么你选择的算法 执行的计算次数量应该在 10^ 8 量级,才能解决这类问题
例题: 求循环节长度
#include<iostream> #include<algorithm> #include<vector> using namespace std; int f(int n,int m){ n = n % m; //求 小数的循环节,这步消除了整数部分的数字 vector<int> v; for(;;){ v.push_back(n); n *= 10; n = n % m; if(n == 0) return 0; if(find(v.begin(),v.end(),n) != v.end()){ //vector 中 从前往后找n,如果找到了n,返回的是n在 vector 中的位置 //在下方填入代码 如果没有找到,则返回 v.end() ,其值为空 } } } int main(){ int n,m; cin >> n >> m; cout << f(n,m) << endl; return 0; }
插入的代码:
return (int) (v.end() - find(v.begin(),v.end(),n));
初次求模运算消除整数部分的数字,在之后的每次计算时,先n * 10,再n 取余m, 看余数是否出现过,如果余数出现过,就认为“开始了循环"
也可以看看这篇博客
https://blog.csdn.net/zm15229608646/article/details/79551977
二、字符串
例题:
#include<iostream> #include<string> using namespace std; int main(){ int n; cin >> n; for(int i = 1;i <= n;i++){ string space = string(/* 请在这里填写代码 */,' '); string ch = string(/* 请在这里填写代码 */,/* 请在这里填写代码 */); cout << space + ch << endl; } return 0; }
C++有个特殊的构造方法,string xx = string( .....,.....); 前面填整数,后面填字符,表示该字符串由多少个该字符组成
string space = string( n - i,' '); string ch = string(2 * i - 1 ,'A'+i-1);
例题:
#include<stdio.h> int main(){ char c; c = getchar(); if(c >= 'A' && c <= 'Z'){ for(int i = 1;i <= c - 'A' + 1;i++){ for(int j = 1; j <=c - 'A' + 1 - i;j++){ printf(" "); } for(int j = 1;j <= i;j++){ printf("%c",'A'+j-1); } for(int j = i - 1;j >= 1;j--){ printf("%c",'A'+j-1); } printf("\n"); } }else{ for(int i = 1;i <= c - '1' + 1;i++){ for(int j = 1; j <=c - '1' + 1 - i;j++){ printf(" "); } for(int j = 1;j <= i;j++){ printf("%c",'1'+j-1); } for(int j = i - 1;j >= 1;j--){ printf("%c",'1'+j-1); } printf("\n"); } } return 0; }
例题:造房子
样例输出2中,再加一行“+-+-+-+-+”
#include<stdio.h> int main(){ int x,y; scanf("%d %d",&x,&y); for(int i = 0;i < x;i++){ printf("+"); for(int j = 0;j < y;j++){ printf("-+"); } printf("\n|"); for(int j = 0;j < y;j++){ printf("*|"); } printf("\n"); } printf("+"); for(int j = 0;j < y;j++){ printf("-+"); } return 0; }
例题:
输入: 2
输出: ABA
#include<stdio.h> #include<string.h> char res[5000000]; int main(){ int n; scanf("%d",&n); int len = 0; for(int i = 1;i <= n;i++){ strcat(/* 插入代码 */,res); res[len] = 'A' + i - 1; len = strlen(res); } printf("%s\n",res); return 0; }
strcat(res + len + 1, res );
例题:寻找字符串
gets() 不会吃掉最后的换行,但由于对输入的长度没有限制,所有在C++11中因为不安全被放弃。比赛时勿用
fgets() 会吃掉最后的换行
#include<stdio.h> #include<string.h> char s1[1005],s2[1005]; int main(){ fgets(s1,1004,stdin); //三个参数依次是,存入的字符串,最大长度,从哪里读入 【stdin为标准输入】 fgets(s2,1004,stdin); //fgets() 函数,遇到换行符截止读,但会读入换行符,所以在linux环境下,换行符为\n,windows环境中,换行符为 \r\n //所以,在求相关字符串长度时,灵活根据评测机的环境,-1 / -2 int len1 = strlen(s1)-1,len2 = strlen(s2)-1; int ans = 0; for(int i = 0; i+ len2 - 1 < len1; i++){ bool matched = true; for(int j = 0;j < len2;j++){ if(s1[i + j] != s2[j]) { matched = false; break; } } if(matched) ans++; } printf("%d",ans); return 0; }
三、日期
闰年的判断
int is_leap_year(int year){ if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) return 1; else return 0; }
每个月天数的判断
“一、三、五、七、八、十、腊,三十一天永不差。四、六、九、冬三十整,唯有二月二十八。逢到闰年加一日,如果不加就算差!”
根据日期计算星期几———— 蔡基姆拉尔森计算公式
例:如果是2004-1-10则换算成:2003-13-10来代入公式计算
例题:生日
#include<iostream> #include<string> using namespace std; int is_leap_year(int y){ if(y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)) return 1; else return 0; } int whatday(int y,int m,int d){ int ans = 0; for(int i = 1;i < y;i++){ if(is_leap_year(i)){ ans += 366 % 7; ans %= 7; }else{ ans += 365 % 7; ans %= 7; } } for(int i = 1; i < m;i++){ if(i == 1 || i == 3 || i == 5 || i == 7 ||i == 8 || i == 10 || i == 12){ ans += 31 % 7; ans %= 7; } else if(i == 4 || i == 6 || i == 9 || i == 11){ ans += 30 % 7; ans %= 7; }else if (i == 2){ if(is_leap_year(y)){ ans += 29 % 7; ans %= 7; }else{ ans += 28 % 7; ans %= 7; } } } ans += (d - 1) % 7; //string数组,是从下标0开始,所以所有的计算,应该相应的 -1 操作 ans %= 7; return ans; } string weekday[7] = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}; int main(){ int y,m,d; cin >> y >> m >> d; cout << weekday[whatday(y,m,d)] << endl; return 0; }
例题:恋爱纪念日
#include<stdio.h> int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int main(){ int y,m,d,k; scanf("%d%d%d%d",&y,&m,&d,&k); for(int i = 1;i <= k;i++){ if(y % 400 == 0 || (y % 100 != 0 && y % 4 == 0)){ day[2] = 29; }else{ day[2] = 28; } d++; if(d == day[m] + 1){ m++; d = 1; } if(m == 13){ y++; m = 1; } } printf("%04d-%02d-%02d",y,m,d); //%04d 4位,不足四位用0占位 return 0; }
习题:节假日
简而言之,就是从前往后遍历,如果该天是 周六 or 周天 or 节假日,就 sum++
具体题干可以看下这篇博客:
https://www.cnblogs.com/ACPIE-liusiqi/p/8682905.html
代码:
#include<stdio.h> int mm[10] = {1,5,10,10,10,12}; int dd[10] = {1,1,1,2,3,25}; int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; void nextday(int &y,int &m,int & d){ d++; if(d == day[m] + 1){ d = 1; m++; } } int main(){ int y,w,m,d,sf,ans; scanf("%d",&y); for(int i = 6; i <= 9;i++){ scanf("%d%d",&mm[i],&dd[i]); } scanf("%d",&w); if((y % 400 == 0 || (y % 100 != 0 && y % 4 == 0))){ day[2]++; } m = 1; //从1月1号开始往后推,所以m = 1,d = 1 d = 1; sf = 0; //如果当前是春节第一天,那么春节3天还剩 sf 天 ans = 0; //假期总数 while(m < 13){ if(m == mm[6] && d == dd[6]){ //给出的第二行二数即是春节,位置在mm[6] dd[6],所以优先判断是否是春节 ans++; //如果已经进入春节第一天,则春节假期还有 sf 天 sf = 2; }else if(sf){ //如果进入春节假期,则不断执行这里,直到结束春节假期 ans++; sf--; }else if(w == 6 || w == 7){ //看看是不是周末周六 ans++; }else{ for(int i =0;i < 10;i++){ //看看该天在不在 给定的假期中 if(m == mm[i] && d == dd[i]){ ans++; break; } } } nextday(y,m,d); //下一天 w++; //下一天是星期几 if(w == 8){ w = 1; } } printf("%d",ans); return 0; }