基础数论算法刷题笔记
创始人
2025-05-29 03:13:41
0

理论

最小公倍数、最大公约数

在这里插入图片描述
(a+b)%n = a%n+b%n
(ab)%n = (a%nb%n)%n
a≡2(mod n) —— a%n==2

lcm——最小公倍数
gcd——最大公约数

lcm(a,b) = a*b / gcd(a,b) 最小公倍数=两数的乘积除以最大公约数
但是写程序时应该是 a /gcd(a,b) *b 因为a*b可能会超出数据范围

在这里插入图片描述
例子:
36 21 36对21取模得到15
15 6 21对15取模得到6
3 0 15对6取模得到3,6对3取模得到0,所以3是最大公约数

质数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int euler_phi(int n) {int phi = n;for (int i = 2; i * i <= n; i++) {if (n % i == 0) {phi = phi / i * (i - 1);while (n % i == 0) {n /= i;}}}if (n > 1) {phi = phi / n * (n - 1);}return phi;
}

在这里插入图片描述

求n的质因子

#include 
#include 
using namespace std;
vector primeFactors(int n) {vector factors;for (int i = 2; i * i <= n; i++) {while (n % i == 0) {factors.push_back(i);n /= i;}}if (n > 1) factors.push_back(n);return factors;
}
int main() {int n;cin >> n;vector factors = primeFactors(n);for (int i = 0; i < factors.size(); i++) {cout << factors[i] << " ";}cout << endl;return 0;
}

上述代码中,primeFactors函数用于求一个数的质因子,它的实现方法是:从2开始循环,如果当前数n可以被i整除,则将i加入质因子数组,并将n除以i,直到n不能被i整除为止。当n>1时,说明n是一个质数,将它加入质因子数组中,最后返回质因子数组即可。

练习

[蓝桥杯 2022 省 A] 数的拆分

给定 TTT 个正整数 aia_{i}ai​,分别问每个 aia_{i}ai​ 能否表示为 x1y1⋅x2y2x_{1}^{y_{1}} \cdot x_{2}^{y_{2}}x1y1​​⋅x2y2​​ 的形式,其中 x1,x2x_{1}, x_{2}x1​,x2​ 为正整数,y1,y2y_{1}, y_{2}y1​,y2​ 为大于等于 222 的正整数。

输入格式

输入第一行包含一个整数 TTT 表示询问次数。

接下来 TTT 行,每行包含一个正整数 aia_{i}ai​ 。

输出格式

对于每次询问,如果 aia_{i}ai​ 能够表示为题目描述的形式则输出 yes,否则输出 no

样例输入 #1

7
2
6
12
4
8
24
72

样例输出 #1

no
no
no
yes
yes
no
yes

提示

【样例说明】

第 4,5,74,5,74,5,7 个数分别可以表示为:

a4=22×12;a5=23×12;a7=23×32。\begin{aligned} &a_{4}=2^{2} \times 1^{2} ; \\ &a_{5}=2^{3} \times 1^{2} ; \\ &a_{7}=2^{3} \times 3^{2} 。 \end{aligned} ​a4​=22×12;a5​=23×12;a7​=23×32。​

【评测用例规模与约定】

对于 10%10 \%10% 的评测用例,1≤T≤200,ai≤1091 \leq T \leq 200, a_{i} \leq 10^{9}1≤T≤200,ai​≤109;

对于 30%30 \%30% 的评测用例,1≤T≤300,ai≤10181 \leq T \leq 300, a_{i} \leq 10^{18}1≤T≤300,ai​≤1018;

对于 60%60 \%60% 的评测用例,1≤T≤10000,ai≤10181 \leq T \leq 10000, a_{i} \leq 10^{18}1≤T≤10000,ai​≤1018;

对于所有评测用例,1≤T≤100000,1≤ai≤10181 \leq T \leq 100000,1 \leq a_{i} \leq 10^{18}1≤T≤100000,1≤ai​≤1018 。

蓝桥杯 2022 省赛 A 组 I 题。

思路

  • 有一条引理,满足题目要求的数字也会满足 x12∗x23x_{1} ^{2} *x_{2}^{3}x12​∗x23​
  • 首先埃氏筛选法,找出质因子。因为1018,所以临界的条件是4000
  • 接着,如果给出的询问数本身就是可以成为平方数或者立方数,那么它一定满足条件(sqrt(n)2*13即可)
  • 如果询问的数 aaa 含有质因子,但是质因子 bbb 只出现了一次,就一定不符合条件(因为有质因子 bbb 的话,那么乘积为 aaa 就一定需要这个质因子,但是这个质因子只能出现一次,所以无法满足幂 ≥2≥2≥2 的要求)

题解

#include
using namespace std;// Eratosthenes筛选法
const int N = 4000;
bool isprime[N + 1];
int prime[N / 3], pcnt = 0;
void esieve(void){memset(isprime, true, sizeof isprime);prime[pcnt++] = 2;for (int i = 3; i <= N; i += 2)if (isprime[i]) {prime[pcnt++] = i;for (int j = i + i; j <= N; j += i)isprime[j] = false;}
}typedef long long LL;bool judge(LL n){LL t = sqrt(n);if (t * t == n) return true;t = cbrt(n);if (t * t * t == n) return true;return false;
}int main(){esieve();int t;LL a;scanf("%d", &t);while (t--) {scanf("%lld", &a);if (judge(a)) puts("yes");else {bool flag = true;for (int i = 0; i < pcnt; i++) {int cnt = 0;if (a % prime[i] == 0)while (a % prime[i] == 0)cnt++, a /= prime[i];if (cnt == 1) {flag = false;break;}}puts(flag && judge(a) ? "yes" : "no");}}
}

[蓝桥杯 2021 省 AB2] 完全平方数

一个整数 aaa 是一个完全平方数,是指它是某一个整数的平方,即存在一个 整数 bbb,使得 a=b2a=b^{2}a=b2 。

给定一个正整数 nnn,请找到最小的正整数 xxx,使得它们的乘积是一个完全平方数。

输入格式

输入一行包含一个正整数 nnn。

输出格式

输出找到的最小的正整数 xxx。

样例输入 #1

12

样例输出 #1

3

样例输入 #2

15

样例输出 #2

15

提示

对于 30%30 \%30% 的评测用例, 1≤n≤10001 \leq n \leq 10001≤n≤1000,答案不超过 100010001000。

对于 60%60 \%60% 的评测用例,1≤n≤1081 \leq n \leq 10^{8}1≤n≤108,答案不超过 10810^{8}108。

对于所有评测用例,1≤n≤10121 \leq n \leq 10^{12}1≤n≤1012,答案不超过 101210^{12}1012。

蓝桥杯 2021 第二轮省赛 A 组 G 题(B 组 H 题)。

思路

  • 首先,找到题目中给出的数学规律:完全平方数需要质因子的偶数幂相乘其实自己在做题的时候就已经差不多要思考到这一步了
  • 所以,先将读入的 nnn 进行质因数分解。对于分解的每一个质数,如果它的指数为奇数,则 xxx 的因子就必须有这个质数

题解

#include 
using namespace std;
int main(){long long n,x=1;scanf("%lld",&n);for(long long i=2;i*i<=n;i++)if(n%i==0){int cnt=0;while(n%i==0){n/=i;cnt++;}if(cnt%2==1)x*=i;}if(n!=1)x*=n;printf("%lld\n",x);
}

[蓝桥杯 2017 省 AB] 包子凑数

小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 NNN 种蒸笼,其中第 iii 种蒸笼恰好能放 AiA_iAi​ 个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

每当有顾客想买 XXX 个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有 XXX 个包子。比如一共有 333 种蒸笼,分别能放 333 、 444 和 555 个包子。当顾客想买 111111 个包子时,大叔就会选 222 笼 333 个的再加 111 笼 555 个的(也可能选出 111 笼 333 个的再加 222 笼 444 个的)。

当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有 333 种蒸笼,分别能放 444 、 555 和 666 个包子。而顾客想买 777 个包子时,大叔就凑不出来了。

小明想知道一共有多少种数目是包子大叔凑不出来的。

输入格式

第一行包含一个整数 NNN。(1≤N≤100)(1 \le N \le 100)(1≤N≤100)。

以下 NNN 行每行包含一个整数 AiA_iAi​。(1≤Ai≤100)(1 \le A_i \le 100)(1≤Ai​≤100)。

输出格式

一个整数代表答案。如果凑不出的数目有无限多个,输出 INF

样例输入 #1

2  
4  
5

样例输出 #1

6

样例输入 #2

2  
4  
6

样例输出 #2

INF

提示

对于样例 111,凑不出的数目包括:1,2,3,6,7,111,2,3,6,7,111,2,3,6,7,11。

对于样例 222,所有奇数都凑不出来,所以有无限多个。

蓝桥杯 2017 省赛 A 组 H 题。

思路

  • 首先,如果给出的数不是互质的,即这组数存在一个公因数,所以这组数无论用什么数量关系所能表示的数都是涵盖这个公因数的那么肯定无法表示质数,所以不能表示的数便是INF
  • 后面类似完全背包问题,解法巧妙:f[j]∣=f[j−a[i]]f[j] |= f[j-a[i]]f[j]∣=f[j−a[i]]|=是或运算,这个解法刚好能表达k1x+k2y+……k_{1}x+k_{2}y+……k1​x+k2​y+……
    题解
#include using namespace std;
const int N = 10010;
int a[110], f[N], n; // f[i]表示i是否能被表示出来int gcd(int a,int b) return a % b == 0 ? b : gcd(b, a % b);int main(){cin>>n;for(int i=0; i < n; i++)cin>>a[i];int g = a[0];for(int i = 1; i < n; i++) g = gcd(g, a[i]);if (g != 1) cout << "INF" << endl;else   //完全背包问题{f[0]=1;for(int i = 0; i < n; i++)for(int j = a[i]; j < N; j++)f[j] |= f[j - a[i]];  //这里很巧妙int ans=0;for (int i = 1; i < N; i++)ans += !f[i];cout << ans << endl;}
}

[蓝桥杯 2016 省 AB] 最大比例

X 星球的某个大奖赛设了 MMM 级奖励。每个级别的奖金是一个正整数。

并且,相邻的两个级别间的比例是个固定值。

也就是说:所有级别的奖金数构成了一个等比数列。比如:

16,24,36,5416,24,36,5416,24,36,54

其等比值为:3/23/23/2。

现在,我们随机调查了一些获奖者的奖金数。

请你据此推算可能的最大的等比值。

输入格式

第一行为数字 N(0

第二行 NNN 个正整数 Xi(Xi<1012)X_i(X_i<10^{12})Xi​(Xi​<1012),用空格分开。每个整数表示调查到的某人的奖金数额。

输出格式

一个形如 A/BA/BA/B 的分数,要求 AAA、BBB 互质。表示可能的最大比例系数。

测试数据保证了输入格式正确,并且最大比例是存在的。
样例输入 #1

3
1250 200 32

样例输出 #1

25/4

样例输入 #2

4
3125 32 32 200

样例输出 #2

5/2

样例输入 #3

3
549755813888 524288 2

样例输出 #3

4/1

提示

时限 3 秒, 256M。蓝桥杯 2016 年第七届省赛

蓝桥杯 2016 年省赛 A 组 J 题(B 组 J 题)。
思路

  • 观察题目给出的样例,会发现给出的数与数之间的比值应该是比例系数k1/k2k_{1}/k_{2}k1​/k2​的 iii 次幂在做题的时候能想到这些,但是关于后面的实现没什么思路
  • 所以,只需要求出比值中分子分母的最大公约数
  • 由于我们事先不知每项比值的幂,因此无法通过辗转相除法来做,而求幂的最大公约数可以通过辗转相减法来做对于两个数,我们可以使用辗转相除法通过相除再取模的方式来求它们的最大公约数。但是,对于多个数,这种方法就不适用了。 例如,如果我们要求三个数12、18和30的最大公约数,我们无法通过简单的相除再取模的方式来进行计算。如果我们依次求出12和18的最大公约数、18和30的最大公约数,然后再求这两个最大公约数的最大公约数,这样的计算方式比较繁琐且容易出错。 相反,如果我们将这些数进行分解质因数,并找出它们的公共质因数,就可以直接求出它们的最大公约数。但是,对于多个数分解质因数的复杂度比较高,因此在这种情况下,使用辗转相减法可能更为方便。通过询问chatgpt得到的(我觉得能理解的解释)

题解

#include
using namespace std;
typedef long long ll;
const int maxn = 110;
ll a[maxn], b[maxn], x[maxn];
ll gcd(ll a, ll b) return (!b)?a:gcd(b, a%b);
ll gcd_sub(ll a, ll b){if(a < b) swap(a, b);if(b == 0) return a;return gcd_sub(b, a-b);
}
int main(){int n;while(cin >> n){for(int i = 1; i <= n; i++) cin >> x[i];sort(x+1, x+1+n);int cnt = 0;for(int i = 2; i <= n; i++){if(x[i] != x[i-1]){cnt++;ll tmp = gcd(x[i], x[i-1]);a[cnt] = x[i-1] / tmp;b[cnt] = x[i] / tmp;}}ll son = a[1], parent = b[1];for(int i = 2; i <= cnt; i++){son = gcd_sub(son, a[i]);parent = gcd_sub(parent, b[i]);}cout << parent << "/" << son << endl;}
}

[蓝桥杯 2017 国 C] 小数第 n 位

我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数。

如果我们把有限小数的末尾加上无限多个 000,它们就有了统一的形式。

本题的任务是:在上面的约定下,求整数除法小数点后的第 nnn 位开始的 333 位数。

输入格式

一行三个整数:aaa,bbb,nnn,用空格分开。aaa 是被除数,bbb 是除数,nnn 是所求的小数后位置(0

输出格式

一行 333 位数字,表示:aaa 除以 bbb,小数后第 nnn 位开始的 333 位数字。

样例输入 #1

1 8 1

样例输出 #1

125

样例输入 #2

1 8 3

样例输出 #2

500

样例输入 #3

282866 999000 6

样例输出 #3

914

提示

时限 1 秒, 256M。蓝桥杯 2017 年第八届国赛

思路

  • 一开始我的思考是直接将a∗pow(10,n)a *pow(10,n)a∗pow(10,n),然后去个位和小数位前2位。这个算法思想倒是没错,但是忽略了一个关键的问题:在a∗pow(10,n)a*pow(10,n)a∗pow(10,n)之后,无法保证aaa不超出数据范围所以,对于编程题,尽量减少大额的乘法
  • 所以,只能牺牲一定的时间,依次乘以1010,然后n-10因为给出的数据最大在109所以不会超出数据范围

题解

#include
long long a,b,c,d,e;
int main(){scanf("%d%d%d",&a,&b,&c);a=a%b;while(c>10){    a*=1e10;c-=10;a=a%b;}for(int i=0;ia*=10;if(i>=c-1)e=a/b,printf("%d",e);a=a%b;}printf("\n");
}

总结

  1. 数论的题目,首先分析题目的意思,分解成数论相关的模型
  2. 接着,思路往自己学过的数论知识上靠——质因子、质数、最大公约数辗转相除法、辗转相乘法、公因数

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...