1.日期处理
在蓝桥杯比赛中日期处理是经常考的题目是难点也是重点,但做出题目的方法有很多,Excel表格熟练的同学可以用Excel表格做出来,但用Excel表格做会花费很长时间才能做出来,而且不一定能作对,感觉很不划算,今天我们用C语言一起来解决它
1.1预备知识
1.1.1swap函数
swap函数是C++中algorithm头文件下的函数,其作用是交换两个数的值
swap(x,y)用来交换x,y,的值
代码示例
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int x,y;
cin>>x>>y;
swap(x,y);
cout<<x<<" "<<y<<endl;
return 0;
}
一个n位整数x取后m位数组成的数:x%pow(10,m),pow(a,b)表示a的b次方在math.c里面,去前n-m位数:x/pow(10,n-m)
1.2数据的多组输入
与单组数据输入测试相比多组数据测试一次能运行所有数据,并且结果都是正确的
1.2.1while…EOF
在C语言中,或更精确地说成C标准函数库中表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。可以用于多组输入
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int a[100010];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
printf("%d",n);
}
return 0;
}
在这"scanf("%d",&n) != EOF"相当于"scanf("%d",&n) != EOF",或"~scanf("%d",&n)",或"scanf("%d",&n) == 1 " 。scanf的返回值由后面的参数决定
1.2.2while(t–)
其中t为测试的次数
1.2.3while(cin>>a)
用于检测IO流的输入流是否正常,正常返回true,否则返回false
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int a[100010];
int main()
{
int a;
while(cin>>a)
{
cout<<a<<endl;
}
return 0;
}
1.3取两个日期之间相差的天数
思路解析
设两个日期time1、time2,相差日期ans,time1在前,time2在后,具体处理:每当ans加1,time1加1,直到time1等于time2。
注意问题:
- 平年和闰年及判断
- 当time1加一后的天数d等于当前月份天数加一时,d置为1,月份m加1,当m等于13时,m置为1,年份y加1
参考代码
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int day[13][2]={0,0,31,31,28,29,31,31,30,30,31,31,30,30,31,31,31,31,30,30,31,31,30,30,31,31};//保存每月的天数
bool judge(int x)//平年、闰年判断
{
if((x%4==0&&x%100!=0)||x%400==0)
return true;
return false;
}
int main()
{
int year1,year2,y1,y2,m1,m2,d1,d2;
while(scanf("%d %d",&year1,&year2)!=EOF)//多组输入
{
if(year1>year2)//将日期设为year1<year2
{
swap(year1,year2);
}
//分别取年、月、日
y1=year1/10000;
m1=year1%10000/100;
d1=year1%100;
y2=year2/10000;
m2=year2%10000/100;
d2=year2%100;
int ans=0;//设置相差天数为0,例2020/1/1与2020/1/2相差一天
while(y1<y2||m1<m2||d1<d2)
{
ans++;//相差天数加1
d1++;
if(d1==day[m1][judge(y1)]+1)//当d1比当前月份天数大一天(天数满足当前天数)
{
d1=1;//天置为1
m1++;//月份加1
}
if(m1==13)//当过了12月
{
m1=1;//月份置为1
y1++;//年份加1
}
}
cout<<ans<<endl;
}
}
2进制转换
在生活经常使用的是10进制,而计算机当中经常使用二进制,另外还有八进制,十六进制。他们之间的进制转换‘必须掌握
2.1将p进制x转为十进制y
将其转为10进制y
代码演示
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int p,x;//p进制数x
cin>>x>>p;
int ans=0;//转化为十进制的结果
int y=1;//每位数乘的p的次方项p^0,p^1,p^2...p^n-1
while(x)
{
int a=x%10;//去x的每一位数
x=x/10;
ans+=a*y;
y=y*p;
}
cout<<ans<<endl;
return 0;
}
2.2将十进制的x转为p进制的y
通常采用“除基取余法”,所说的基是指要转换的进制p,除基取余的意思是每次将待转数除以p,然后将所的得到的数最为地位存储,而商则继续除以p并进行上面的操作,最后当商为0时,将所有从低到高的输出就可以得到z。
代码演示
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
int main()
{
int x,p;//十进制x,以及要转换的进制p
cin>>x>>p;
stack <int> ans;
do //do..while循环排除x为0的情况
{
int m=x%p;//求基取余
x=x/p;
ans.push(m);//将每一位结果存入栈中
}while(x);
while(!ans.empty())//将结果输出
{
cout<<ans.top();
ans.pop();
}
return 0;
}
2.3将p进制x转为n进制y
思路:先将p进制x转化为10进制的z,在将10进制的z转为n进制的y
3 字符串
字符串是常见的题型也是常考的题型,为了在蓝桥杯中那个好成绩,字符串的题目必须都会,常见的有回文字符串,字符串排序,以及字符串搜索和最长回文字串
3.1回文字符串
像"a",“aba”,"abba"这种从前往后和从后往前读是一样的字符串为回文字符串
常用知识点:reverse函数和字符串比较
代码演示:
#include <stdio.h>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
int main()
{
string s;
cin>>s;
string s1=s;
reverse(s1.begin(),s1.end());
if(s1==s)
cout<<"Yes";
else
cout<<"No";
return 0;
}
3.2字符串排序
题目描述:输入一个整数n代表字符串的个数,在接下来的n行每行输出一个字符串,其中输出顺序为长度长的在前短的在后,如果长度相同,字典序大的在前小的在后
3.3字符串中子串的个数
https://pintia.cn/problem-sets/994805260223102976/problems/994805282389999616
4.贪心
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。也就是说,不从整体最优上加以考虑,做出的只是在某种意义上的局部最优解 。
具体例题讲解一:https://pintia.cn/problem-sets/994805260223102976/problems/994805301562163200
具体例题讲解二:https://pintia.cn/problem-sets/994805260223102976/problems/994805298269634560
区间贪心:
具体例题讲解三:http://codeup.cn/problem.phpcid=100000584&pid=0
4.组合数计算
组合数C(n,m)是指从n个不同的数m中选出n个方案的个数,常见有两种计算方法
4.1根据C(n,m)=n!/m!/(n-m)!
#include <bits/stdc++.h>
using namespace std;
long long sum(int n)//利用递归求n!函数
{
if(n==0||n==1)
return 1;
else
return n*sum(n-1);
}
int main()
{
int n,m;
cin>>n>>m;
cout<<sum(n)/sum(m)/sum(n-m);//根据公式求答案
return 0;
}
4.2根据递推公式C(n,m)=C(n-1,m)+C(n-1,m-1),C(n,n)=C(0,0)=1
#include <bits/stdc++.h>
using namespace std;
long long ans[60][60];
long long sum()//利用递归求n!函数
{
for(int i=0;i<60;i++)
{
ans[i][i]=ans[i][0]=1;
}
for(int i=2;i<60;i++)
{
for(int j=1;j<=i/2;j++)
{
ans[i][j]=ans[i-1][j]+ans[i-1][j-1];
ans[i][i-j]=ans[i][j];
}
}
}
int main()
{
sum();
cout<<ans[35][28]<<endl<<ans[4][2]<<endl<<ans[5][2]<<endl<<ans[2][1]<<endl<<ans[3][2];
return 0;
}