当前位置: 首页 > news >正文

蓝桥杯基础数论入门

一.试除法

首先我们要了解,所有大于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.csdn.net/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;
    }
}

相关文章:

  • freecad 窗口控件层级关系
  • DIA——边缘检测
  • 腾讯后端 C++一面:recv 返回值,什么错误是可接受的?
  • vue3+vite+ts使用daisyui/tailwindcss
  • 微信小程序跳2
  • 【数据结构 · 初阶】- 单链表
  • 算法训练之动态规划(三)
  • Python 实现如何电商网站滚动翻页爬取
  • 亚马逊Amazon商品详情API接口概述,json数据示例返回(测试)
  • opencv人脸性别年龄检测
  • Zotero PDF Translate 翻译插件使用OpenAI API配置教程
  • vue+flask图书知识图谱推荐系统
  • Next.js + Droplet:高并发视频内容平台部署与优化扩展实战
  • 小迪安全-tp框架反序列化,利用链,rce执行,文件删除
  • AI助手:Claude
  • 深入理解全排列算法:DFS与回溯的完美结合
  • 高级java每日一道面试题-2025年3月23日-微服务篇[Nacos篇]-如何使用Nacos进行服务发现?
  • SpringBoot企业级开发之【用户模块-更新用户基本信息】
  • OSPF不规则区域
  • ubuntu20.04在mid360部署direct_lidar_odometry(DLO)
  • 网站测试域名301怎么做/企业所得税优惠政策
  • 南京网站开发个人/设计网站的软件
  • 如何做网站预览/桂林seo排名
  • 网站建设 工作方案/ip域名查询地址
  • 专业微网站建设公司首选公司/百度优化是什么
  • flash网站项目背景/十大互联网平台