数论 - 约数 - 试除法求约数 + 约数个数 + 约数之和 + 最大公约数
1、 试出法求约数
给定n个正整数ai,对于每个整数ai,请你按照从小到大的顺序输出它的所有约数。
输入格式
第一行包含整数n。
接下来n行,每行包含一个整数ai。
输出格式
输出共n行,其中第 i 行输出第 i 个整数ai的所有约数。
数据范围
1≤n≤100,
2≤ai≤2∗109
输入样例:
2
6
8
输出样例:
1 2 3 6
1 2 4 8
分析:
O ( n ) 的 做 法 , 枚 举 一 个 较 小 的 因 子 , 另 一 个 直 接 用 原 数 去 除 。 O(\sqrt{n})的做法,枚举一个较小的因子,另一个直接用原数去除。 O(n)的做法,枚举一个较小的因子,另一个直接用原数去除。
注 意 完 全 平 方 数 只 要 加 入 一 个 因 子 。 注意完全平方数只要加入一个因子。 注意完全平方数只要加入一个因子。
代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N=110;
int n;
void solve(int x)
{
vector<int> p;
for(int i=1;i<=x/i;i++)
if(x%i==0)
{
p.push_back(i);
if(i!=x/i) p.push_back(x/i);
}
sort(p.begin(),p.end());
for(int i=0;i<p.size();i++) cout<<p[i]<<' ';
cout<<endl;
}
int main()
{
cin>>n;
while(n--)
{
int x;
cin>>x;
solve(x);
}
return 0;
}
2、约数个数
给定n个正整数ai,请你输出这些数的乘积的约数个数,答案对109+7取模。
输入格式
第一行包含整数n。
接下来n行,每行包含一个整数ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需对109+7取模。
数据范围
1≤n≤100,
1≤ai≤2∗109
输入样例:
3
2
6
8
输出样例:
12
正 整 数 a 的 约 数 个 数 : 由 算 术 基 本 定 理 , 设 A = P 1 a 1 P 2 a 2 . . . P k a k , 则 A 的 约 数 个 数 为 ( a 1 + 1 ) ( a 2 + 1 ) . . . ( a k + 1 ) 。 正整数a的约数个数:\\由算术基本定理,设A=P_1^{a_1}P_2^{a_2}...P_k^{a_k},则A的约数个数为(a_1+1)(a_2+1)...(a_k+1)。 正整数a的约数个数:由算术基本定理,设A=P1a1P2a2...Pkak,则A的约数个数为(a1+1)(a2+1)...(ak+1)。
说 明 : 设 A 的 一 个 约 数 A ′ = P 1 b 1 P 2 b 2 . . . P k b k , 其 中 b i ∈ [ 0 , a i ] , i ∈ [ 1 , k ] 。 说明: \\设A的一个约数A'=P_1^{b_1}P_2^{b_2}...P_k^{b_k},其中b_i∈[0,a_i],i∈[1,k]。 说明:设A的一个约数A′=P1b1P2b2...Pkbk,其中bi∈[0,ai],i∈[1,k]。
每 一 个 k 元 组 ( b 1 , b 2 , . . . , b k ) 均 能 对 应 A 的 一 个 约 数 , 对 于 每 个 b i 都 有 a i + 1 种 取 值 , \\每一个k元组(b_1,b_2,...,b_k)均能对应A的一个约数,对于每个b_i都有a_i+1种取值, 每一个k元组(b1,b2,...,bk)均能对应A的一个约数,对于每个bi都有ai+1种取值,
根 据 乘 法 原 理 , 不 同 的 k 元 组 的 个 数 即 A 的 所 有 约 数 的 个 数 为 C a 1 + 1 1 C a 2 + 1 1 . . . C a k + 1 1 = ( a 1 + 1 ) ( a 2 + 1 ) . . . ( a k + 1 ) 。 根据乘法原理,不同的k元组的个数即A的所有约数的个数为C_{a_1+1}^1C_{a_2+1}^1...C_{a_k+1}^1=(a_1+1)(a_2+1)...(a_k+1)。 根据乘法原理,不同的k元组的个数即A的所有约数的个数为Ca1+11Ca2+11...Cak+11=(a1+1)(a2+1)...(ak+1)。
具体落实:
问 题 转 化 分 解 A 的 所 有 质 因 数 并 保 存 每 个 质 因 数 的 指 数 , 再 用 公 式 。 问题转化分解A的所有质因数并保存每个质因数的指数,再用公式。 问题转化分解A的所有质因数并保存每个质因数的指数,再用公式。
代码:
#include<iostream>
#include<unordered_map>
#define ll long long
#define x first
#define y second
using namespace std;
const int mod=1e9+7;
int n;
unordered_map<int,int> P;
int main()
{
cin>>n;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x/i;i++)
while(x%i==0)
{
x/=i;
P[i]++;
}
if(x>1) P[x]++;
}
ll res=1;
for(auto p: P)
res=res*(p.y+1)%mod;
cout<<res<<endl;
return 0;
}
3、约数之和
给定n个正整数ai,请你输出这些数的乘积的约数之和,答案对109+7取模。
输入格式
第一行包含整数n。
接下来n行,每行包含一个整数ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对109+7取模。
数据范围
1≤n≤100,
1≤ai≤2∗109
输入样例:
3
2
6
8
输出样例:
252
正 整 数 a 的 约 数 个 数 : 由 算 术 基 本 定 理 , 设 A = P 1 a 1 P 2 a 2 . . . P k a k , 则 A 的 约 数 之 和 为 ∏ i = 1 k ∑ j = 0 a i P i j 。 正整数a的约数个数:\\由算术基本定理,设A=P_1^{a_1}P_2^{a_2}...P_k^{a_k},则A的约数之和为\prod_{i=1}^k\sum_{j=0}^{a_i}P_i^j。 正整数a的约数个数:由算术基本定理,设A=P1a1P2a2...Pkak,则A的约数之和为∏i=1k∑j=0aiPij。
即 ( P 1 0 + P 1 1 + . . . + P 1 a 1 ) ( P 2 0 + P 2 1 + . . . + P 2 a 2 ) . . . ( P k 0 + P k 1 + . . . + P k a k ) 即(P_1^0+P_1^1+...+P_1^{a_1})(P_2^0+P_2^1+...+P_2^{a_2})...(P_k^0+P_k^1+...+P_k^{a_k}) 即(P10+P11+...+P1a1)(P20+P21+...+P2a2)...(Pk0+Pk1+...+Pkak)
说
明
:
说明:
说明:
设
A
的
一
个
约
数
A
′
=
P
1
b
1
P
2
b
2
.
.
.
P
k
b
k
,
其
中
b
i
∈
[
0
,
a
i
]
,
i
∈
[
1
,
k
]
。
设A的一个约数A'=P_1^{b_1}P_2^{b_2}...P_k^{b_k},其中b_i∈[0,a_i],i∈[1,k]。
设A的一个约数A′=P1b1P2b2...Pkbk,其中bi∈[0,ai],i∈[1,k]。
每 一 个 k 元 组 ( b 1 , b 2 , . . . , b k ) 均 能 对 应 A 的 一 个 约 数 , 对 于 每 个 质 因 子 P i x , x 均 有 a i + 1 种 选 法 , 每一个k元组(b_1,b_2,...,b_k)均能对应A的一个约数,对于每个质因子P_i^{x},x均有a_i+1种选法, 每一个k元组(b1,b2,...,bk)均能对应A的一个约数,对于每个质因子Pix,x均有ai+1种选法,
现 需 在 k 个 形 如 { P i 0 , P i 1 , . . . , P i a i } 的 集 合 中 选 一 个 p i x , i ∈ [ 1 , k ] , x ∈ [ 0 , a i ] , 现需在k 个形如\{P_i^0,P_i^1,...,P_i^{a_i}\}的集合中选一个p_i^{x},i∈[1,k],x∈[0,a_i], 现需在k个形如{Pi0,Pi1,...,Piai}的集合中选一个pix,i∈[1,k],x∈[0,ai],
选 k 次 , 每 次 对 应 一 个 约 数 P 1 x 1 P 2 x 2 . . . P k x k , 最 终 求 和 结 果 为 : 选k次,每次对应一个约数P_1^{x_1}P_2^{x_2}...P_k^{x_k},最终求和结果为: 选k次,每次对应一个约数P1x1P2x2...Pkxk,最终求和结果为: ( P 1 0 + P 1 1 + . . . + P 1 a 1 ) ( P 2 0 + P 2 1 + . . . + P 2 a 2 ) . . . ( P k 0 + P k 1 + . . . + P k a k ) (P_1^0+P_1^1+...+P_1^{a_1})(P_2^0+P_2^1+...+P_2^{a_2})...(P_k^0+P_k^1+...+P_k^{a_k}) (P10+P11+...+P1a1)(P20+P21+...+P2a2)...(Pk0+Pk1+...+Pkak)
具体落实:
① 、 首 先 对 A 分 解 质 因 数 , 并 记 录 每 个 质 因 数 的 指 数 , 用 一 个 哈 希 表 存 储 。 ①、首先对A分解质因数,并记录每个质因数的指数,用一个哈希表存储。 ①、首先对A分解质因数,并记录每个质因数的指数,用一个哈希表存储。
② 、 求 P i 0 + P i 1 + P i 2 + . . . + P i a i 可 以 用 迭 代 来 做 , t = t ∗ P i + 1 , 迭 代 a i + 1 次 。 当 然 也 可 以 用 等 比 数 列 求 和 公 式 、 分 治 等 方 法 。 ②、求P_i^{0}+P_i^{1}+P_i^{2}+...+P_i^{a_i}可以用迭代来做,t=t*P_i+1,迭代a_i+1次。\\\qquad当然也可以用等比数列求和公式、分治等方法。 ②、求Pi0+Pi1+Pi2+...+Piai可以用迭代来做,t=t∗Pi+1,迭代ai+1次。当然也可以用等比数列求和公式、分治等方法。
代码:
#include<iostream>
#include<unordered_map>
#define ll long long
#define x first
#define y second
using namespace std;
const int mod=1e9+7;
int n;
unordered_map<int,int> prime;
int main()
{
cin>>n;
while(n--)
{
int x;
cin>>x;
for(int i=2;i<=x/i;i++)
while(x%i==0)
{
x/=i;
prime[i]++;
}
if(x>1) prime[x]++;
}
ll res=1;
for(auto p : prime)
{
ll t=0;
for(int i=0;i<=p.y;i++)
t=(t*p.x+1)%mod;
res=res*t%mod;
}
cout<<res<<endl;
return 0;
}