蓝桥杯知识点复习

参考链接:

蓝桥杯常用知识点+算法汇总 - 程帅霞 - 博客园 (cnblogs.com)

                                            算法细节

1. %.3f保留3位小数并四舍五入
2. &&的优先级要高与||和&&有点类似于*,||类似于+

3:

1 if(1)
2         if(b)
3             x++;
4         else  //else默认和最近的一个if配对
5             y++;

4. if(fabs(m*my-n*ny)<0.000001)
//浮点数判断相等,要近似判断,如果用==得不到结果。
//fabs(float x)浮点数x的绝对值 来源 蓝桥杯 鸡蛋的数目


5. 质数:又称素数:在大于1的自然数中,除了1和它本身以外不再有其他因数。


6. 互质数:公因数只有1的两个非零自然数


7. 同余定理: 例如:1234%10
1234%10=(((1%10*10+2)%10*10+3)%10*10+4)%10


8. 高次方数的尾数:
规律:1-100中 凡是有因子5,尾数就增加一个零;有因子25,尾数就增加两个零。
100!有24个零,1000!有249个零。


9. 大衍数列 0、2、4、8、12、18、24、32、40、50、60、72、84

 

 1 int main()
 2 {
 3     int i;
 4     for(i=1; i<100; i++)
 5     {
 6         if(i%2==0) //填空
 7             printf("%d \n", i*i/2);
 8         else
 9             printf("%d \n", (i*i-1)/2);
10     }
11     printf("\n");
12 }

10: 数字规律:1,3,6,10,,,,

  公式:i*(i+1)/2

 

11:唯一分解定理:

 1 ll getfac(ll x)//唯一分解定理
 2 {
 3     ll ans=1;
 4     for(int i=1;i<=cnt&&primel[i]*primel[i]<=x;i++)
 5     {
 6         ll sum=0;
 7         while(x%primel[i]==0)
 8         {
 9             sum++;
10             x/=primel[i];
11         }
12         ans*=(sum+1);
13     }
14     if(x>1)
15     ans*=2;
16     return ans;
17 }

 

12:  一年的12个月:1-12月

   31、28/29、31、30、31、30、31、31、30、31、30、31

      闰年: (year%4==0&&year%100!=0)||(year%400==0)

 

 13: 辗转相除法求最大公约数

1 int gcd(int a, int b)
2 {  
3     if (b == 0) return a;  
4     else return gcd(b, a % b);  
5 } 

14:埃氏筛法(搜索n以内的所有素数)

 1 int prime[MAX_N];//第i个素数  
 2 bool is_prime[MAX_N + 1];  
 3  
 4 //返回n以内素数的个数  
 5 int sieve(int n) {  
 6     int p = 0;
 7     for (int i = 0; i <= n; i++)  
 8         is_prime[i] = true;  
 9     is_prime[0] = is_prime[1] = false;  
10     for (int i = 2; i <= n; i++) {  
11         if (is_prime[i]){  
12             prime[p++] = i;  
13             for (int j = 2*i; j <= n; j += i)  
14                 is_prime[j] = false;  
15         }  
16     }  
17     return p;  
18 } 

15:筛选法求素数 

1 memset(vis,0,sizeof(vis));  
2 for (int i=2;i<=n;i++)
3 {  
4     for (int j=i*2;j<=n;j+=i) vis[j]=1;  
5 }  

  升级版    素数定理 不超过x的素数个数近似(略超过) x/lnx;

1 int m=sqrt(n+0.5);  
2 memset(vis,0,sizeof(vis));  
3 for (int i=2;i<=m;i++)   
4     if (!vis[i])  
5     for (int j=i*i;j<=n;j+=i) vis[j]=1;

16:.快速幂取模

b9e635bd15107852c4ae4ea93a631e8c.gif

1 long long quick_mod(long long a,long long b){  
2     long long res=1;  
3     while(b!=0){  
4         if (b%2==1) res*=(a%n);  
5         a=a*(a%n);  
6         b/=2;  
7     }  
8     return res;  
9 }  

f530e368d53b178864547bfacd0c992c.gif

  但是当数据量大于10^19时,longlong会爆,所以利用快速乘法,原理类似,a*b就是b个a相加,将b表示为二进制:

48c252ad78c0accbf0e2f7673c851d57.gif

 1 int n;  
 2 long long mul(long long a,long long b){  
 3     long long res=0;  
 4     while(b!=0){  
 5         if(b%2==1) res=(res+a%n)%n;  
 6         a=(a%n+a%n)%n;  
 7         b/=2;  
 8     }  
 9     return res;  
10 }  
11   
12 long long quick_mod(long long a,long long b){  
13     long long res=1;  
14     while(b!=0){  
15         if (b%2==1) res=mul(res,a)%n;  
16         a=mul(a,a);  
17         b/=2;  
18     }  
19     return res;  
20 } 

557e184f5967b95edfcc670349fd73b2.gif

 17:二分排序

4b9415196a08abf0e0802d607396f94c.gif

 1 /* nums[]指的是有序数组;low指的是数组下标0;high指的是数组下标n-1(n指的是数组长度);target指的是要插入的目标元素 */
 2 void sort(int nums[],int low,int high,int target) {
 3     int n=high+1;
 4     // 当low<=high一直循环折半查找,当low>high时结束循环
 5     while(low<=high) {
 6         int mid=(low+high)/2;// 计算中间下标
 7         if(nums[mid]>=target) { // 如果大于等于要插入的元素,则high=mid-1
 8             high=mid-1;
 9         } else if(nums[mid]<target) { // 如果小于要插入的元素,在low=mid+1
10             low=mid+1;
11         }
12     }
13     // 然后将nums[high+1]之后的所有元素(包括nums[high+1])向后移动一个位置
14     for(int i=n; i>high+1; i--) {
15         nums[i]=nums[i-1];
16     }
17     // 然后将空出来的nums[high+1]赋为target值
18     nums[high+1]=target;
19 }

50df40b46f64d76b4014468c6961f64a.gif

 18:错排 An=n-1(An-1+An-2)

 19:进制转换

af3721e6168aa704ddc4a0b5e2f24e92.gif

 1 #include "stdio.h"
 2 int a[10000];
 3 int main()
 4 {
 5     int r,n;
 6     char d;
 7     while(~scanf("%d%d",&n,&r))
 8     {
 9         int e=n;
10         if(n<0)
11             n=-n;
12             int i=0,j;
13         while(n!=0)
14         {
15             a[i]=n%r;
16             n=n/r;
17             i++;
18         }
19         for(j=i-1; j>=0; j--)
20         {
21             if(e<0)
22             {
23                 if(j==i-1)
24                     printf("-");
25                 if(a[j]>9)
26                 {
27                     d=a[j]-10+'A';
28                     printf("%c",d);
29                 }
30                 else
31                     printf("%d",a[j]);
32             }
33             else
34             {
35                 if(a[j]>9)
36                 {
37                     d=a[j]-10+'A';
38                     printf("%c",d);
39                 }
40                 else
41                     printf("%d",a[j]);
42             }
43         }
44         printf("\n");
45     }
46     return 0;
47 }

02f546f24d6156e325a04ebd5049ea2e.gif

 20:  01背包

    解决办法:声明一个 大小为  m[n][c] 的二维数组,m[ i ][ j ] 表示 在面对第 i 件物品,且背包容量为  j 时所能获得的最大价值 ,那么我们可以很容易分析得出 m[i][j] 的计算方法,

    (1). j < w[i] 的情况,这时候背包容量不足以放下第 i 件物品,只能选择不拿

      m[ i ][ j ] = m[ i-1 ][ j ]

    (2). j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更大的价值。

        如果拿取,m[ i ][ j ]=m[ i-1 ][ j-w[ i ] ] + v[ i ]。 这里的m[ i-1 ][ j-w[ i ] ]指的就是考虑了i-1件物品,背包容量为j-w[i]时的最大价值,也是相当于为第i件物品腾出了w[i]的空间。

        如果不拿,m[ i ][ j ] = m[ i-1 ][ j ] , 同(1)

      究竟是拿还是不拿,自然是比较这两种情况那种价值最大。

    

1 if(j>=w[i])
2     m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);
3 else
4     m[i][j]=m[i-1][j];

21:完全背包问题

  完全背包表示每个物品可以取无限次,只要加起来总容量不超过V就可以。
  同样可以用f[i][j]表示前i间物品恰放入一个容器为j的背包可以获得的最大价值。则其状态转移方程为:
  f[i][j] = max{f[i-1][j-k*weight[i]] + k*value[i]} ,其中(0 <= k <= j/weight[i])

 22:多重背包问题

  多重背包是每个物品有不同的个数限制,如第i个物品个数为num[i]。
  同样可以用f[i][j]表示前i间物品恰放入一个容器为j的背包可以获得的最大价值,且每个物品数量不超多num[i]。则其状态转移方程为:
  f[i][j] = max{f[i-1][j-k*weight[i]] + k*value[i]} ,其中(0 <= k <= min{j/weight[i], num[i]})

 

                                                 常考概念

1:最大公约数:也称最大公因子,指两个或多个整数共有约数中最大的一个

(81条消息) 一文搞定最大公约数(四种方法,赋原理和比较,超详细解答)_Stella_sss的博客-CSDN博客_最大公约数定理

 

(81条消息) 【C/C++】求最大公约数的三种方法_chen_zan_yu_的博客-CSDN博客_编写程序求最大公约数

2:最小公倍数:公倍数(common multiple)是指在两个或两个以上的自然数中,如果它们有相同的倍数,这些倍数就是它们的公倍数。公倍数中最小的,就称为这些整数的最小公倍数

C语言求最小公倍数(详解版) (biancheng.net)

3:快速幂:

(81条消息) 快速幂算法(全网最详细地带你从零开始一步一步优化)_刘扬俊的博客-CSDN博客_快速幂

4:进制转化

#include<iostream>
#include<algorithm>
#include<math.h>
#include<bits/stdc++.h>
using namespace std;

int t=-1;//因为第一个计算出来的数应该乘pow(10,0) 
int change(long long int num,long long int FC){
    long long int sum=0;
    while(num!=0){//t
        int mo=num%FC;
        t++;
        num=num/FC;
        sum=sum+mo*pow(10,t);
        cout<<sum<<endl; 
    }
    return sum;
} 
int main(){
    long long  int n;
    long long int FC=2;
    long long int num=20;//十进制转换 
    long long int t=change(num,FC);
    cout<<t<<endl;
    return 0;
} 

数组有序函数sort()

#include<iostream>
#include<time.h>
#include<algorithm>
#include<string.h>
//#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b){
	return a<b;
	}
int main(){
	int a[100]={0};
	for(int i=0;i<100;i++){
		a[i]=rand()%20;
		cout<<a[i]<<" ";
	}
	cout<<endl;
	sort(a,a+100,cmp);
	for(int i=0;i<100;i++){
		
		cout<<a[i]<<" ";
	}
}

辗转相除求最大公因数

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
#include<math.h>
using namespace std;
int gcd(int a,int b){
	if(b==0)return a;
	else{
		cout<<a<<" "<<b<<endl; 
		gcd(b,a%b);
	}
}
int main(){
	//辗转相除求最大公因数
	int a=1002;
	int b=32;
	
	 int t=gcd(a,b);
	 cout<<t<<endl;
}

(6)最小公倍数

最小公倍数(Least Common Multiple,LCM),如果有一个自然数a能被自然数b整除,则称a为b的倍数,b为a的约数,对于两个整数来说,指该两数共有倍数中最小的一个。计算最小公倍数时,通常会借助最大公约数来辅助计算。

最小公倍数=两数的乘积/最大公约(因)数,解题时要避免和最大公约(因)数问题混淆。

对于最小公倍数的求解,除了利用最大公约数外,还可根据定义进行算法设计。要求任意两个正整数的最小公倍数即,求出一个最小的能同时被两整数整除的自然数。

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
#include<math.h>
using namespace std;
//最小公倍数=两数的乘积/最大公约(因)数,
int gcd(int a,int b){
	if(b==0)return a;
	else{
		cout<<a<<" "<<b<<endl; 
		gcd(b,a%b);
	}
}
int main(){
	int a=1010;
	int b=10;
	int t=gcd(a,b);
	cout<<a*b/t<<endl;
}

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半截詩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值