算法-蓝桥杯

输入输出加速:

cin/cout/scanf/printf:

cin.tie(0);
ios::sync_with_stdio(false);

基础算法:

排序:

//快排模板
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
int q[N];
void quick(int q[], int l, int r){
   
    if(l >= r){
   
        return;
    }
    //x是取得比较位,i,左边界,j,右边界
    int x = q[(l + r) / 2], i = l - 1, j = r + 1;
    while(i < j){
   
        do i++; while( q[i] < x);
        do j--; while( q[j] > x);
        if(i < j) swap( q[i], q[j]);
    }
    quick(q, l, j);
    quick(q, j + 1, r);
}
int main(){
   
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
   
        scanf("%d",&q[i]);
    }
    quick(q, 0, n - 1);
    
    for(int i = 0; i < n; i++){
   
        cout << q[i] << " ";
    }
    return 0;
}
//归并排序

位运算:

数学知识:

数论:

质数

(数论) O(1)
结论:

如果 a,b 均是正整数且互质,那么由 ax+by,x≥0,y≥0 不能凑出的最大数是 ab−a−b

下面给出证明:

首先证明 ab−a−b不能被 ax+bx,x≥0,y≥0表示出。
反正法,假设 ab−a−b=ax+by,那么 ab=a(x+1)+b(y+1),由于 a|ab,a|a(x+1),所以 a|b(y+1),由于 a,ba,b 互质,所以 a|(y+1),由于 y≥0,所以 a<=y+1,所以 b(y+1)≥ab。同理可得 a(x+1)≥ab,所以 a(x+1)+b(y+1)≥2ab>ab,矛盾。

证明 ab−a−b+d,d>0 一定可以表示成 ax+by,x,y≥0的形式。

原题链接:

质数的定义: 是针对大于1的自然数,小于等于1的既不是质数也不是合数。
在大于1的整数中,如果只包含本身这两个约数,就被称作质数或素数。

暴力解法(试除法)

//判定一个数是否为质数
bool isPrime(a) {
   
  if (a < 2) return 0;
  for (int i = 2; i < a; ++i)
    if (a % i == 0) return 0;
  return 1;
}
//时间复杂度为O(N)
//判定一个数是否为质数
n可以整除 d, n同样可以整除 n/d;
//约数都是成对出现的,所以我们可以枚举较小的数
//即 d <= n/d,可以写成d <= sqrt(n);
//由于sqrt() 运算速度慢, d * d <= n,在(d + 1) * (d + 1) <= n时,
//会存在溢出风险,使得d^2为负值,故不尝试
bool isPrime(a) {
   
  if (a < 2) return 0;
  for (int i = 2; i < a / i; ++i)
    if (a % i == 0) return 0;
  return 1;
}
//时间复杂度为O(sqrt(N))

分解质因数(试除法)
例:给定n个正整数ai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。

//从小到大枚举所有数, 
void divide(int n){
   
	for(int i = 2; i < n; i++){
   
		if(n % i == 0){
   
			int s = 0;
			while(n % i){
   
				n /= i;
				s++;
			}
			cout << i << s;
		}
	}
	if(n > 1) cout << n << 1;
}

例:筛质数
给定一个正整数n,请你求出1~n中质数的个数。

const int N = 1000010;
bool st[N];
int primes[N];
int cnt;
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;
        }
    }
}

埃拉托斯特尼筛法

const int N = 1000010;
bool is_prime[N];
int prime[N];
int p;

int Eratosthenes(int n) {
   
  int p = 0;
  for (int i = 0; i <= n; ++i) is_prime[i] = 1;
  //is_prime 设置为0则不是质数
  is_prime[0] = is_prime[1] = 0;
 
  for (int i = 2; i <= n; ++i) {
   
    if (is_prime[i]) {
   
      prime[p++] = i;  // prime[p]是i,后置自增运算代表当前素数数量
      for (int j = i + i; j <= n; j += i)  // 因为从 2 到 i - 1 的倍数我们之前筛过了
           is_prime[j] = 0;           
           // 这里直接从 i的倍数开始,提高了运行速度
        // 是i的倍数的均不是素数
    }
  }
  return p;
}
}

线性筛法

n只会被最小质因子筛掉。
分为两种情况:
1. i % pj == 0:
	pj一定是i的最小质因子,pj一定是pj * i 的最小质因子。
2. i % pj != 0;
	pj一定小于i的所有质因子,pj一定时pj * i 的最小质因子。
 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;
	}
}

最大公约数/最小公倍数

最大公约数

/*
a mod b = a - (a / b) * b;
		= a - c * b;
a / d, b / d, ax + by / d;
(a, b) = (b, a % b)


*/
int gcd(int a, int b){
   
	return b ? gcd(b, a % b) : a;
}

最小公倍数

a * b / gcd(a, b);

试除法求约数:
给定n个正整数ai,对于每个整数ai,请你按照从小到大的顺序输出它的所有约数。

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())
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值