数论-约数
因数,也称为约数(英语:Divisor)是一个常见的数学名词,用于描述自然数 和自然数 之间存在的整除关系,即 可以被 整除。这里我们称 是 的倍数, 是 的因数或因子。
试除法求约数#
试除法的思路很简单和求质数一样,求一个数的所有约束,可以枚举从 的所有数,把它记录下来。这里有一个优化,如果 那么 ,所以约束也是成对出现的,只要枚举 和 之中较小的那个即可。只需要使 即只需要枚举到 。
【问题描述】
给定 个正整数 ,对于每个整数 ,请你按照从小到大的顺序输出它的所有约数。
【输入格式】
第一行包含整数 。
接下来 行,每行包含一个整数 。
【输出格式】
输出共 行,其中第 行输出第 个整数 的所有约数。
【输入样例】
2
6
8
【输出样例】
1 2 3 6
1 2 4 8
#include<bits/stdc++.h>
using namespace std;
vector<int> div(int n) {
vector<int> ans;
for (int i = 1; i <= n / i; i ++) {
if (n % i == 0) {
ans.push_back(i);
if (i != n / i) ans.push_back(n / i); // 注意边界情况,有可能出现 n/i == i的情况导致重复加入数值
}
}
sort(ans.begin(), ans.end());
return ans;
}
int main()
{
int n;
cin >> n;
while (n --) {
int x; cin >> x;
auto ans = div(x);
for (auto t : ans) cout << t << ' ';
cout << endl;
}
return 0;
}
约数的个数#
自然数 N 的因数个数以 表示。若 唯一分解为
,
则
例如 ,则其正因数个数 。
【问题描述】
给定 个正整数 ,请你输出这些数的乘积的约数个数,答案对 取模。
【输入格式】
第一行包含整数 。
接下来 行,每行包含一个整数 。
【输出格式】
输出一个整数,表示所给正整数的乘积的约数个数,答案对 取模。
【输入样例】
3
2
6
8
【输出样例】
12
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
map<int, int> p;
int main()
{
int n, x;
cin >> n;
while (n --) {
cin >> x;
for (int i = 2; i <= x / i; i ++) {
if (x % i == 0) {
while (x % i == 0) x /= i, p[i] ++;
}
}
if (x > 1) p[x] ++;
}
ll ans = 1;
for (auto t : p) ans = ans * (t.second + 1) % mod; // define的时候mod不是整型,是double不能取模,const int mod = 1e9 + 7比较保险。
cout << ans;
return 0;
}
给定任意一个数,求其约数的个数。上题相当于求 的约数的个数。
约数之和#
自然数 的正因数和,以因数函数 表示。由质因数分解而得。
若 唯一分解为 , 则
再由等比级数求和公式可知,上式亦可写成:
例如,则其正因数之和
【问题描述】
给定 个正整数 ,请你输出这些数的乘积的约数之和,答案对 取模。
【输入格式】
第一行包含整数 。
接下来 行,每行包含一个整数 。
【输出格式】
输出一个整数,表示所给正整数的乘积的约数之和,答案对 取模。
【输入样例】
3
2
6
8
【输出样例】
252
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
int main()
{
int n;
map<int, int> p;
cin >> n;
while (n --) {
int x; cin >> x;
for (int i = 2; i <= x / i; i ++) {
if (x % i == 0) {
while (x % i == 0) x /= i, p[i] ++;
}
}
if (x > 1) p[x] ++;
}
ll ans = 1;
for (auto t : p) {
int a = t.first, b = t.second;
ll k = 1;
while (b --) k = (k * a + 1) % mod;
ans = ans * k % mod;
}
cout << ans;
return 0;
}
代码前半部分与之前几乎一样,后半部分很像秦九韶算法,主要是用于计算等比数列和。
例如 可以写成 ,CPU
计算加法比乘法快,可以算的快一点也可以采用快速幂计算等比数列前项和
最大公约数#
求最大公约数一般采用欧几里得算法,欧几里得算法的核心其实是下面进行证明
-
对进行变换
-
证明对于和的任意公约数,都是和的公约数
是的公约数,同时也是 的公约数 -
证明对于和的任意公约数,都是和的公约数
即证明是的公约数,可以整除,则可以整除所以可以整除
综上所述,集合等于集合,则,该过程的实现如下
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
顺便一提,最小公倍数的求法
int lcm(a, b) {
return a / gcd(a, b) * b; // 不要写成a*b/gcd(a, b)可能会溢出,先除会让数小一些
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效