【第十四届蓝桥杯考前速成】必考知识点及代码模板总结,看完至少多拿50分

慈云数据 2024-04-10 技术支持 61 0

文章目录

  • 写在前面
  • 一、年份日期问题
    • 1、闰年判定
    • 2、月份天数
    • 二、简单算法
      • 1、前缀和
      • 2、差分
      • 3、二分
      • 4、并查集
      • 二、简单数论
        • 1、质数判定
        • 2、筛质数
        • 3、进制转换
          • (1)其他进制转十进制
          • (2)十进制转其他进制
          • 4、保留小数
          • 5、最大公约数
          • 6、最小公倍数
          • 7、快速幂
          • 三、常用STL
            • 1、string
            • 2、vector
            • 3、queue/priority_queue
            • 4、stack
            • 5、set/multiset
            • 6、map/multimap
            • 7、unordered_set/unordered_map
            • 8、pair
            • 9、algorithm
            • 四、简单图论
              • 1、单源最短路径
              • 2、多源最短路
              • 3、最小生成树
              • 五、动态规划
                • 1、0-1背包
                • 2、完全背包
                • 3、多重背包
                • 4、线性DP
                • 总结

                  写在前面

                  • 本文章面向第十四届蓝桥杯考生,在最后考前几天,方便自己总结与回顾,同时将其分享给大家,希望我们都能取得心仪的成绩。
                  • 本文章主要给出代码模版,对算法具体流程不会具体讲解,所以不太适合零基础的同学,适用于有一定算法基础,在考前想要进行复习与总结的同学。
                  • 文章大部分代码模版参考于y总,同时自己添加了一些常考知识点,y总代码模版参考处。
                  • 由于时间紧迫,给出了部分选看内容,如果学有余力的同学可以了解一下,在考试中可以多过一些测试点,多拿一些分。

                    一、年份日期问题

                    1、闰年判定

                    • 闰年:年份能够被4整除但不能被100整除或者能被400整除的为闰年。

                      代码模版

                      【第十四届蓝桥杯考前速成】必考知识点及代码模板总结,看完至少多拿50分
                      (图片来源网络,侵删)
                      bool isryear(int n){
                           return n%400==0||(n%4==0&&n%100!=0);
                      }
                      

                      2、月份天数

                      • 口诀:一三五七八十腊,三十一天永不差。闰年2月29天,平年2月28天。

                        代码模板

                        //也可以将数组第一个位置空出来,即填上一个随意的值,这样就可以将月份和数组下标对应了,方便访问
                        int pmonths[]={31,28,31,30,31,30,31,31,30,31,30,31};   //平年每月天数
                        int rmonths[]={31,29,31,30,31,30,31,31,30,31,30,31};   //闰年每年天数
                        

                        二、简单算法

                        1、前缀和

                        一维前缀和

                        【第十四届蓝桥杯考前速成】必考知识点及代码模板总结,看完至少多拿50分
                        (图片来源网络,侵删)
                        预处理出s[],s[i]存储前i个数的和
                        s[i]=a[1]+a[2]+...+a[i]
                        计算[l,r]区间和=s[r]-s[l-1]
                        

                        二维前缀和

                        左上角坐标为(1,1),右下角坐标为(i,j)的前缀和(区域内所有数的和)
                        s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]
                        求左上角坐标为(x1,y1),右下角坐标为(x2,y2)的前缀和
                        s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]
                        
                        • 参考例题:这里

                          2、差分

                          一维差分

                          int b[N];       //b为差分数组,直接定义为全局即可,如果要对某个数组进行差分操作,直接先将该数组中每个数进行insert(i,i,a[i])操作即可得到a的差分数组b
                          //对区间[l,r]进行差分操作时
                          void insert(int l,int r,int c){
                          	b[l]+=c;
                          	b[r+1]-=c;
                          }
                          //差分完后对b数组求前缀和即可,求完前缀和后的b数组即进行完对某些区间加减某个数操作后的原数组
                          

                          二维差分

                          int b[N][N];     //差分数组 
                          //对左上角坐标为(l1,r1),右下角坐标为(l2,r2)的矩阵进行差分操作时
                          void insert(int l1,int r1,int l2,int r2,int c){
                          	b[l1][r1]+=c;
                          	b[l1][r2+1]-=c;
                          	b[l2+1][r1]-=c;
                          	b[l2+1][r2+1]+=c; 
                          } 
                          //同样,差分操作完成后对b数组求前缀和,即可得到对原数组某些区域加减某个数后操作的原数组
                          
                          • 参考例题:这里

                            3、二分

                            //首先确定区间的二段性:二部分分别满足不同的性质。以任意一部分的性质作为check条件,如果mid满足check判断区间应该缩小到哪部分,如果在[l,mid]利用模板1,如果在[mid,r]利用模板2 
                            //模版1
                            int l=0,r=n;    //二分区间[l,r] 
                            while(l
                            	int mid=l+r>1;
                            	if(check(mid)) r=mid;
                            	else l=mid+1;
                            } 
                            //模版2
                            int l=0,r=n;    //二分区间[l,r] 
                            while(l
                            	int mid=l+r+1>1;
                            	if(check(mid)) l=mid;
                            	else r=mid-1;
                            } 
                            //算法结束l=r,l、r均为结果 
                            
                            • 参考例题:这里

                              4、并查集

                              代码模板

                              int p[N];     //祖宗结点数组 
                              for(int i=1;i     //查找祖宗结点 
                              	if(p[x]!=x) p[x]=find(p[x]);
                              	return p[x];
                              } 
                              p[find(a)]=find(b);    //合并a,b集合 
                              
                              	if(n
                              		if(n%i==0) return false;
                              	}
                              	return true;
                              }
                              
                              	st[0]=st[1]=true;
                              	for(int i=2;i
                              		if(!st[i]){
                              			primes[cnt++]=i;
                              			for(int j=i+i;j
                              				st[j]=true;
                              			}
                              		}
                              	}
                              }
                                 //n表示传入的是多少进制数,s为n进制数 
                              	int ans=0;
                              	for(int i=0;i
                              		ans=ans*n+s[i]-'0';
                              	}
                              	return ans;
                              }
                              //传入为数组,num为数组中元素个数
                              int ntoten(int a[],int num,int n){
                                  int ans=0;
                                  for(int i=0;i
                                      ans=ans*n+a[i];
                                  }
                              }
                                 //nums为需要转换的数,n为需要转换的进制数
                                  stack
                                  	s.push(nums%n);
                                  	nums/=n;
                              	}
                              	while(!s.empty()){
                              	    cout   //nums为需要转换的数,n为需要转换的进制数
                                  int cnt=0;     //记录数组中元素个数
                                  while(nums){
                                  	a[cnt++]=nums%n;
                                  	nums/=n;
                              	}
                              	reverse(a,a+cnt);
                              	for(int i=0;i
                              	return b?gcd(b,a%b):a;
                              }
                              
                              	LL res=1%p;
                              	while(b){
                              		if(b&1) res=res*a%p;
                              		b=1;
                              		a=(LL)a*a%p;
                              	}
                              	return res;
                              } 
                              
                                   return ab;
                              }
                              sort(a,a+n,cmp);
                              //对结构体指定属性排序,例:
                              struct Student{
                                    string name;
                                    double score;
                              }stu[N];
                              bool cmp(Student A,Student B){
                                   return A.scoreB.score;
                              }
                              //按成绩降序排序
                              sort(stu,stu+n,cmp);
                              max()       //取最大值
                              min()       //取最小值
                              swap()      //交换两个元素的值
                              reverse()   //传参和sort一致,反转区间内的元素顺序
                              unqiue()    //传参和和sort一致,去重相邻的相同元素,若原序列无序首先需排序,返回去重后原序列尾迭代
                              
                              	memset(dist,0x3f,sizeof dist);
                              	dist[1]=0;
                              	for(int i=0;i    //迭代n次 
                              		int t=-1;
                              		for(int j=1;j   //寻找距离最小的点 
                              			if(!st[j]&&(t==-1||dist[t]dist[j])) t=j;
                               		}
                               		st[t]=true;      //标记为已确定 
                               		for(int j=1;j
                              	e[idx]=b;
                              	w[idx]=c;
                              	ne[idx]=h[a];
                              	h[a]=idx++;
                              }
                              int spfa(){
                              	memset(dist,0x3f,sizeof dist);
                              	queue
                              		int t=q.front();
                              		q.pop();
                              		st[t]=false;
                              		for(int i=h[t];i!=-1;i=ne[i]){
                              			int j=e[i];
                              			if(dist[j]dist[t]+w[i]){
                              				dist[j]=dist[t]+w[i];
                              				if(!st[j]){
                              					st[j]=true;
                              					q.push(j);
                              				}
                              			}
                              		}
                              	}
                              	if(dist[n]==0x3f3f3f3f) return -3;
                              	else return dist[n];
                              } 
                              
                              	for(int j=1;j
                              		if(i==j) d[i][j]=0;
                              		else d[i][j]=0x3f3f3f3f;
                              	}
                              }
                              void floyd(){
                              	for(int k=1;k
                              		for(int i=1;i
                              			for(int j=1;j
                              				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
                              			}
                              		} 
                              	}
                              }
                              //注意,若图中存在负权边,所以1号点无法到n号点,d[1][n]也可能被更新也可能则d[i][j]若大于0x3f3f3f3f/2即可认为最短路不存在 
                              
                              	memset(dist,0x3f,sizeof dist);
                              	int res=0;     //存储最小生成树边权重之和 
                              	for(int i=0;i
                              		int t=-1;
                              		for(int j=1;j    //寻找距离当前生成树最小的点 
                              			if(!st[j]&&(t==-1||dist[t]dist[j])) t=j;
                              		}
                              		if(i&&dist[t]==0x3f3f3f3f3) return 0x3f3f3f3f;    //如果距离最小的点的距离仍然是正无穷说明无最小生成树 
                              		if(i) res+=dist[t];
                              		for(int j=1;j     //并查集find操作 
                              	if(p[x]!=x) p[x]=find(p[x]);
                              	return p[x];
                              }
                              struct Edge{      //存储每条边 
                              	int a,b,w;
                              }edges[M]; 
                              bool cmp(Edge A,Edge B){    //手写cmp,使sort能为结构体排序 
                              	return A.w
                              	for(int i=1;i
                              		int a=edges[i].a,b=edges[i].b,w=edges[i].w;
                              		if(find(a)!=find(b)){           //最小边权的起点和终点a,b不在一个连通块则合并他们 
                              			p[find(b)]=find(a);
                              			res+=w;
                              			cnt++;
                              		}
                              	}
                              	if(cnt    //枚举每个物品 
                              	for(int j=m;j=v[i];j--){   //逆序枚举背包体积 
                              		dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
                              	}
                              }
                                  //枚举每个物品 
                              	for(int j=v[i];j   //正序枚举背包体积 
                              		dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
                              	}
                              }
                                  //枚举每个物品 
                              	for(int j=m;j=v[i];j--){   //逆序枚举背包体积 
                              		for(int k=0;k
                              			dp[j]=max(dp[j],dp[j-k*v[i]]+k*w[i]);
                              		}
                              	}
                              }
                              
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon