当前位置: 首页 > 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 7return 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开始,步长为pfor (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;}
}


http://www.mrgr.cn/news/97964.html

相关文章:

  • UE学习记录part15
  • OSPF接口的网络类型和不规则区域
  • 17. git fetch
  • 41、web前端开发之Vue3保姆教程(五 项目实战)
  • 2025年4月7日--4月13日(learn openg+dx+ogre+bullet+ue5肉鸽)
  • Linux入门指南:从零开始探索开源世界
  • Kaggle-Digit Recognizer-(多分类+卷积神经网络CNN)
  • react从零开始的基础课
  • linux下截图工具的选择
  • Python刷题笔记
  • PointNet++语义分割(semseg)训练自己的数据集并完成可视化并保存txt结果
  • 浅入浅出 DeepSeek R1
  • elasticSearch-搜索引擎
  • Kaggle-Housing Prices-(回归+Ridge,Lasso,Xgboost模型融合)
  • Web前端之Vue+Element实现表格动态不同列合并多行、localeCompare、forEach、table、push、sort、Map
  • C#容器源码分析 --- List
  • vue2添加背景水印-手动实现(无组件模式)
  • Python 实现的运筹优化系统数学建模详解(最大最小化模型)
  • Vue3+Vite+TypeScript+Element Plus开发-11.Pinia持久化处理
  • 【图书管理系统】深入解析基于 MyBatis 数据持久化操作:全栈开发图书管理系统获取图书列表接口(后端:计算图书页数、查询当前页展示的书籍)