2013年第四届蓝桥杯省赛真题C++ B组
2014年第五届蓝桥杯省赛真题C++ B组
2016年第七届蓝桥杯省赛真题C++ B组
2017年第八届蓝桥杯省赛真题C++ B组
2018年第九届蓝桥杯省赛真题C++ B组
2019年第十届蓝桥杯省赛真题C++ B组
2020年第十一届蓝桥杯省赛第二场(10月17日)真题C++ B组
2021年第十二届蓝桥杯省赛第一场(5月9日)真题C++ B组
CC150给出算法题五种解法
2013-高斯日记、2020-跑步锻炼
在用excel的时候计算1月1日到1月3日的天数应该是两天,但是左侧的的行数是3,记得到时候-1,视情况而定
int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool is_leap(int year){
return year%400==0||(year%4==0&&year%100!=0);
}
int get_days(int year,int month){
if(month==2){
return 28+is_leap(year);
}else{
return days[month];
}
}
有时候直接求余2021年第一场的时间显示
用stl中的函数实现。
do{
//按提议操作
}while(next_permutation(a,a+n))
参考数字翻转
bool huiwen(int x){
int y=x,num=0;
while(y){
num=num*10+y%10;
y/=10;
}
if(num==x) return true;
else return false;
}
类似数字翻转的代码。
void fanzhuan(int x){
int y=x;
while(y){
int t=y%10;
//对t进行一些操作判断(依据题意来看)
y/=10;
}
}
long long fact(int n){
long long ans=1;
for(int i=1;i<=n;i++){
ans*=i;
}
return ans;
}
long long C(int n,int m){
if(m<n-m) m=n-m;
long long ans=1;
for(int i=m+1;i<=n;i++) ans*=i;
for(int i=1;i<=n-m;i++) ans/=i;
return ans;
}
void Yanghui(int n){
for(int i=0;i<=n;i++) C[i][0]=C[i][i]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=i;j++){
C[i][j]=C[i-1][j]+C[i-1][j-1];
}
}
}
//调用
Yanghui(n+max(a,b));//参数传下面的数字。
杨辉三角中第i 行第j 列的数字正是C i j 的结果!!!
bool is_prime(int n){
if(n<2) return false;
for(int i=2;i<=n/i;i++){
if(n%i==0) return false;
}
return true;
}
const int N=10000;
int primes[N],cnt; //存放素数
bool st[N]; //判断x是否被删掉
void get_primes(int n){
for(int i=2;i<=n;i++){
if(!st[i]){ //如果没有被删掉的话对他处理
primes[cnt++]=i;
for(int j=i+i;j<=n;j+=i){
st[j]=true; //删掉j,注意这里是j
}
}
}
}
当数据量到1e7的时候运行时间是埃氏的一半
const int N=10000;
int primes[N],cnt; //存放素数
bool st[N]; //判断x是否被删掉
void get_primes(int n){
for(int i=2;i<=n;i++){
if(!st[i]) primes[cnt++]=i;
for(int j=0;primes[j]<=n/i;j++){
st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
unordered_map<int,int> map;
void divide(int n) {
for (int i = 2; i <= n / i; i++) {
if (n % i == 0) {
int c = 0;
while (n % i == 0) {
c++;
n /= i;
}
map[i] += c;
}
}
// 还要加上大于根号n的素因子
if (n >= 2) map[n]++;
}
分解质因数的输出
unordered_map<int,int>::iterator it;
for(it=map.begin();it!=map.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
简单递归
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
最小公倍数a*b/gcd(a,b)
试除法求约数
vector<int> get_divisors(int n){
vector<int> res;
for(int i=1;i<=n/i;i++){
if(n%i==0){
res.push_back(i);
if(i!=n/i) res.push_back(n/i);
}
}
sort(res.begin(),res.end());
return res;
}
有时候枚举答案的时候,如果需要枚举的数字正好是需要找的到数的因子,可以先把因子数组找出来,如找三个数乘积是2021041820210418(16位数字)的时候,如果从1开始遍历的话肯定是跑不出来的,所以最好先找出这个数的因子。
int a[5000],len;
void find_divisor(int n){
for(int i=1;i<=n/i;i++){
if(n%i==0){
a[len++]=i;
if(i!=n/i){
a[len++]=n/i;
}
}
}
}
约数个数定理
一个大于1的正整数n可以分解质因数:
则n的正约数的个数就是:
套用因子分解模板
#include
#include
using namespace std;
unordered_map<int,int> map;
void divide(int n){
for(int i=2;i<=n/i;i++){
if(n%i==0){
int c=0;
while(n%i==0){
c++;
n/=i;
}
map[i]+=c;
}
}
if(n>1) map[n]++;
}
int main()
{
divide(8);
unordered_map<int,int>::iterator it;
long long res=1,mod=1e9+7;
for(it=map.begin();it!=map.end();it++){
res=res*(it->second+1)%mod;
}
cout<<res<<endl;
} // namespace std;
约数和定理
f(n)=(p1^0 + p1^1 + p1^2 +… p1^a1) (p2^0 + p2^1 + p2^2+…p2 ^ a2) … (pk ^0 + pk ^ 1 + pk ^ 2 +…pk^ak)
套用因子分解模板
#include
#include
using namespace std;
unordered_map<int,int> map;
void divide(int n){
for(int i=2;i<=n/i;i++){
if(n%i==0){
int c=0;
while(n%i==0){
c++;
n/=i;
}
map[i]+=c;
}
}
if(n>1) map[n]++;
}
int main()
{
divide(8);
unordered_map<int,int>::iterator it;
long long res=1,mod=1e9+7;
for(it=map.begin();it!=map.end();it++){
int p=it->first,a=it->second;
long long t=1;
while(a--) t=(t*p+1)%mod;
res=res*t%mod;
}
cout<<res<<endl;
} // namespace std;
#include
using namespace std;
int G[50][50];
int m,a,b;
int main()
{
cin>>m;
for(int i=0;i<m;i++){
cin>>a>>b;
G[a][b]=1;
}
for(int i=1;i<=m;i++){
int sum=0;
for(int j=1;j<=m;j++){
if(G[i][j]==1){
sum++;
}
}
cout<<i<<"和"<<sum<<"条边相连"<<endl;
}
return 0;
} // namespace std;
#include
#include
using namespace std;
vector<int> v[50];
int m,a,b;
int main()
{
cin>>m;
for(int i=0;i<m;i++){
cin>>a>>b;
v[a].push_back(b);
v[b].push_back(a);
}
for(int i=1;i<=m;i++){
cout<<i<<":";
int v_size=v[i].size();
for(int j=0;j<v_size;j++){
cout<<v[i][j]<<" ";
}
cout<<endl;
}
return 0;
} // namespace std;
输入&输出
#include
using namespace std;
int fa[20001];
void init(int n){
for(int i=1;i<=n;i++) fa[i]=i;
}
int find(int x){
if(x==fa[x]) return x;
else{
fa[x]=find(fa[x]); //父节点设为根节点
return fa[x]; // 返回父节点
}
}
void unionn(int i,int j){
int i_fa=find(i); //找到i的祖先
int j_fa=find(j); //找到j的祖先
fa[i_fa]=j_fa; //i的祖先指向j的祖先,其实j的祖先先指向i的祖先
}
int main()
{
int n,m,x,y,q;
cin>>n;
init(n);
cin>>m;
for(int i=1;i<=m;i++){
cin>>x>>y;
unionn(x,y);
}
cin>>q;
for(int i=1;i<=q;i++){
cin>>x>>y;
if(find(x)==find(y)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
} // namespace std;
例题
【DFS专题训练】踏青 C++程序题 连通块问题
【DFS专题训练】迷宫解的方案数 C++程序题
【DFS专题训练】最大蛋糕数 C++程序题 求最大连通块数
【广度优先搜索BFS】总结
【DFS专题训练】一维坐标的移动
algorithm
sort(a,a+n);//sort(数组名+开始下标,数组名+结束下标,函数名)
int a[MAX_SIZE];
bool cmp(int a,int b){
return a>b;
}
sort(a+1,a+1+n,cmp);
将数字常量转换为字符串
在头文件string
中
reverse(a.begin(),a,end());
reverse(a+1,a+1+n);
第一点:在unique之前必须保证去重数组有序,也就是得sort一下。
第二点:unique并不会生成一个新的数组,而是将原数组多余的部分“移”到了数组之后,同时unique本身还会返回一个指针,指向去重之后的最后一位。
第三点:该函数常用于离散化,利用迭代器(或指针)的减法,可计算出去重后元素的个数。
int length = unique(a.begin(),a,end()) - a.begin();
int length = unique(a+1,a+1+n)-(a+1);
int index = lower_bound(a+1,a+1+n,x)-a;
size() 返回元素个数
empty() 返回是否为空
clear() 清空
front()/back()
push_back()/pop_back()
begin()/end()
[]
支持比较运算,按字典序
first, 第一个元素
second, 第二个元素
支持比较运算,以first为第一关键字,以second为第二关键字(字典序)
size()/length() 返回字符串长度
empty()
clear()
substr(起始下标,(子串长度)) 返回子串
c_str() 返回字符串所在字符数组的起始地址
size()
empty()
push() 向队尾插入一个元素
front() 返回队头元素
back() 返回队尾元素
pop() 弹出队头元素
size()
empty()
push() 插入一个元素
top() 返回堆顶元素
pop() 弹出堆顶元素
定义成小根堆的方式:priority_queue, greater> q;
size()
empty()
push() 向栈顶插入一个元素
top() 返回栈顶元素
pop() 弹出栈顶元素
size()
empty()
clear()
begin()/end()
++, -- 返回前驱和后继,时间复杂度 O(logn)
set/multiset
insert() 插入一个数
find() 查找一个数
count() 返回某一个数的个数
erase()
(1) 输入是一个数x,删除所有x O(k + logn)
(2) 输入一个迭代器,删除这个迭代器
lower_bound()/upper_bound()
lower_bound(x) 返回大于等于x的最小的数的迭代器
upper_bound(x) 返回大于x的最小的数的迭代器
map/multimap
insert() 插入的数是一个pair
erase() 输入的参数是pair或者迭代器
find()
[] 注意multimap不支持此操作。 时间复杂度是 O(logn)
lower_bound()/upper_bound()
和上面类似,增删改查的时间复杂度是 O(1)
不支持 lower_bound()/upper_bound(), 迭代器的++,--
int l=0,r=n-1;
while(l<r){
int mid=(l+r)>>1;
if(q[mid]>=x) r=mid;
else l=mid+1;
}
int l=0,r=n-1;
while(l<r){
int mid=(l+r+1)>>1;
if(q[mid]<=x) l=mid;
else r=mid-1;
}
cout<<l<<endl;
差分原理
前缀和与差分
差分的应用:
b[n]=a[n]-a[n-1]
给定区间[l ,r ],让我们把a数组中的[ l, r]区间中的每一个数都加上c.
转化为b[l]+=c
并且b[r]-=c
输出原序列中从第l个数到第r个数的和
ans=sum[r]-sum[l-1]
#include
#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
}
cout<<f[n][m]<<endl;
return 0;
}
精简版
#include
#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[m]<<endl;
return 0;
}
#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;k*v[i]<=j;k++){
f[i][j]=max(f[i][j],f[i-1][j-v[i]*k]+w[i]*k);
}
}
}
cout<<f[n][m]<<endl;
return 0;
} // namespace std;
精简版
#include
using namespace std;
const int N=1010;
int n,m;
int v[N],w[N];
int f[N][N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(j>=v[i]) f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
}
}
cout<<f[n][m]<<endl;
return 0;
} // namespace std;
2022/03/21
控制输出 printf("%04d%02d%02d",year,month,day);
输出没有取地址符,因为不常用总是忘。
printf的格式控制的完整格式:
% - .n l或h 格式字符
下面对组成格式说明的各项加以说明:
①%:表示格式说明的起始符号,不可缺少。
②-:有-表示左对齐输出,如省略表示右对齐输出。
③0:有0表示指定空位填0,如省略表示指定空位不填。
④m.n:m指域宽,即对应的输出项在输出设备上所占的字符数。N指精度。用于说明输出的实型数的小数位数。为指定n时,隐含的精度为n=6位。
⑤l或h:l对整型指long型,对实型指double型。h用于将整型的格式字符修正为short型。
d格式:用来输出十进制整数。有以下几种用法:
%d:按整型数据的实际长度输出。
%md:m为指定的输出字段的宽度。如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出。
%ld:输出长整型数据。
如果数据类型只有一种的话用pair很方便,调用里面的数据的时候调用属性first
和second
即可。
pair类型的使用相当的繁琐,如果定义多个相同的pair类型对象,可以使用typedef简化声明:
typedef pair<int,int> PII;
set<PII> s;
参考2021年第一场蓝桥杯B组 直线那题。
pair用法
cout<<bitset<8>(10)<<endl;
字符串处理的函数