蓝桥杯基础数论入门

一.试除法

首先我们要了解,所有大于1的自然数都能进行质因数分解。试除法作用如下:

   

  1. 质数判断
    试除法通过验证一个数是否能被小于它的数(一般是用2到用根号x)整除来判断其是否为质数。根据定义,质数只能被1和自身整除。

    示例:判断17是否为质数,需试除2到4(因√17≈4.12),发现无法整除,故17是质数
    bool isPrime(int n) {
        if (n <= 1) return false;
        for (int i=2; i<=n/i; i++) 
            if (n%i == 0) return false;
        return true;
    }

  2. 因数分解
    若目标数是合数,试除法可找到其所有质因数。例如,分解28时,依次试除2、3、5等质数,最终得到质因数2和7

    #include <stdio.h>
    #include <math.h>
    
    void primeFactors(int n) {
        // 处理2的因数
        while (n % 2 == 0) {
            printf("2 ");
            n /= 2;
        }
        // 处理奇数因数(3到√n)
        for (int i = 3; i <= sqrt(n); i += 2) {
            while (n % i == 0) {
                printf("%d ", i);
                n /= i;
            }
        }
        // 处理剩余的大于2的质数
        if (n > 2) {
            printf("%d", n);
        }
    }
    
    int main() {
        int num = 315;
        printf("质因数分解结果:");
        primeFactors(num);  // 输出:3 3 5 7
        return 0;
    }

二.最大公约数 和最小公倍数

最大公约数采用辗转相除法。我们先介绍一下辗转相除法

我们假设大的数为a,小的数为b,求a和b的最大公约数c。

我们用几何理解,我们把a,b看成俩条线。

c是最大公约数,由于定义可得c必须要满足c*n(n为任意正整数)==b,   c*m(m也为任意正整数)==a。简单来说就是可以用正整数的c长度将b,a覆盖。

我们再用二维的视角来看将a和b看成矩形的俩条边。由于要用用正整数的c长度将b,a俩条边覆盖,就是找到一个最大的正方形将这个矩形覆盖。

在我们预先构造的矩形中,我们以短边b构造正方形,然后再去判断用多个正方形能不能在大矩形中放满。这里用取余判断。不能放满的话,我们再在剩余的空间重复判断,剩余空间能放满的话,以短边b构造的正方形肯定可以放满,可以看下面的图理解,6*10的剩余部分能放满,说明这个正方形边长能叠加到10,那么以b为边的正方形肯定可以铺满的。

public static int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

最小公倍数

最小公倍数(a,b)=a*b/(a和b的最大公约数)。

最好先除再乘防止超过范围。

Lcm(a,b)=a/(gcd(a,b))*b;

三.组合数

这里我们用递推公式计算

        可以理解成从n个苹果里面取m个苹果 ,我们先扔掉一个苹果不选,从n-1里苹果个取m个苹果,我们再捡回来扔的苹果并算作m中的一个,并计算缺少的情况,从n-1个苹果中取出m-1个苹果。

对于代码,为了避免重复计算,如下面的红色区域(4,3)重复计算了,我们可以做个记忆化,对于算过的数我们记下。

int v[100][100] = { 0 };//v[n][m];
int dfs(int n,int m)
{
	
	if (m==0||m == n)
	{
		return 1;
	}
	if (v[n][m] != 0)
	{
		return v[n][m];
	}
	else
	{
		int sum = dfs(n - 1, m) + dfs(n - 1, m - 1);
		v[n][m] = sum;
		return sum;
	}

}

int main()
{
	cout<<dfs(5, 3);
}

 四.质数筛

就是给你一个数n,找出1-到的所有质数。

我们可以用试除法一个个找,但是时间复杂度为O(n*n),不太好。

推荐使用埃氏筛(埃拉托斯特尼筛法),很好理解。

原理概况就是,用一个数组表示1到n,我们先假设0到n都是质数,数组的值都是1,然后遍历该质数数组,从2开始,将2的倍数都标记为0。再找到下一个质数,将质数的倍数全部标记为0。就像一个筛子一样,详细原理可以看下面这位大佬,讲解的很详细。

原文链接:https://blog.youkuaiyun.com/Yuki_fx/article/details/115103663

#include <iostream>
#include <vector>
#include <cmath>

std::vector<int> sieveOfEratosthenes(int n) {
    if (n < 2) return {};  // 处理n < 2的情况

    std::vector<bool> isPrime(n + 1, true);
    isPrime[0] = isPrime[1] = false;

 
    for (int p = 2; p <= n/p; ++p) {
        if (isPrime[p]) {
            // 标记p的倍数,从p^2开始,步长为p
            for (int multiple = p * p; multiple <= n; multiple += p) {
                isPrime[multiple] = false;
            }
        }
    }

    // 收集所有质数
    std::vector<int> primes;
    for (int i = 2; i <= n; ++i) {
        if (isPrime[i]) primes.push_back(i);
    }

    return primes;
}

int main() {
    int n;
    
    std::cin >> n;

    std::vector<int> primes = sieveOfEratosthenes(n);

    std::cout << "Primes up to " << n << " are:\n";
    for (int prime : primes) {
        std::cout << prime << " ";
    }
    std::cout << "\n";

    return 0;
}

 五.快速幂

例如求x的n次方,我们可以先求sum=x的2/n次方,再只要求出sum*sum就行,更加快速。需要注意的是如果是奇数要多乘一个x。如2的6次方=2的3次方*2的3次方*2。

int quick(int x,int n)
{
    if (n == 1)
    {
        return x;
    }
    if (n == 0)
    {
        return 1;
    }
    int middle = n / 2;
    int  sum = quick(x, middle);
    if (n % 2 == 0)
    {
        return sum * sum;
    }
    else
    {
        return sum * sum * x;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值