基础数论算法刷题笔记
创始人
2025-05-29 04:26:02
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. 接着,思路往自己学过的数论知识上靠——质因子、质数、最大公约数辗转相除法、辗转相乘法、公因数

相关内容

热门资讯

大数据学习(2) 大数据学习(2)0 数据仓库0.0 数据仓库基本概念0.1 数据仓库主要...
最新或2023(历届)小学生关... 小学生关于法制手抄报的图片模板  小学生关于法制手抄报图片1  小学生关于法制手抄报图片2  小学生...
【spring】javaCon... 目录一、xml形式二、javaConfig形式三、源码分析 一、xml形式 1.spring容器为...
最新或2023(历届)有关法制... 有关法制手抄报的图片模板  有关法制手抄报图片1  有关法制手抄报图片2  有关法制手抄报图片3  ...
最新或2023(历届)有关法制... 有关法制手抄报的图片参考  有关法制手抄报参考图片(1)  有关法制手抄报参考图片(2)  有关法制...
最新或2023(历届)初中生法... 初中生法制手抄报的图片参考  初中生法制手抄报参考图片(1)  初中生法制手抄报参考图片(2)  初...
最新或2023(历届)初中生法... 初中生法制手抄报的图片模板  初中生法制手抄报图片1  初中生法制手抄报图片2  初中生法制手抄报图...
2022湖北省赛 L 裸线段树 有人不会裸线段树有人没有pushdown调了两小时裸线段树早该414了L (codeforces.c...
最新或2023(历届)初中生法... 初中生法制手抄报的图片模板  初中生法制手抄报图片1  初中生法制手抄报图片2  初中生法制手抄报图...
Chapter2.3:线性表的... 该系列属于计算机基础系列中的《数据结构基础》子系列,参考书《数据结构考研复习指导》(王...
最新或2023(历届)初中生法... 初中生法制手抄报的图片参考  初中生法制手抄报参考图片(1)  初中生法制手抄报参考图片(2)  初...
最新或2023(历届)关于简单... 关于简单的法制教育手抄报的图片模板  关于简单的法制教育手抄报图片1  关于简单的法制教育手抄报图片...
最新或2023(历届)关于简单... 关于简单的法制教育手抄报的图片参考  关于简单的法制教育手抄报参考图片(1)  关于简单的法制教育手...
最新或2023(历届)中学生法... 中学生法制教育手抄报的图片模板  中学生法制教育手抄报图片1  中学生法制教育手抄报图片2  中学生...
多种方法跳出线程发包         明文发包CALL是分析一款游戏功能的主要突破口,但是很多游戏都是线程发...
GDKOI2023 D1T1 前言 考场上没想出来,收到来自题目标题的嘲讽 题目大意 求 ∑i=1ni!ik...
Java 造轮子例子 1.要规范地造好一个轮子,以下是一些步骤和建议: 确定你的轮子的功能和用...
最新或2023(历届)中学生法... 中学生法制教育手抄报的图片参考  中学生法制教育手抄报参考图片(1)  中学生法制教育手抄报参考图片...
KubeSphere 社区双周... KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 ...
最新或2023(历届)中学生法... 中学生法制教育手抄报的图片模板  中学生法制教育手抄报图片1  中学生法制教育手抄报图片2  中学生...