标签:个数 lin 质数 方式 iso 数论 简单 names 乘法
对于任何一个大于1的自然数N,如果N不为质数,那么都可以唯一分解成有限个质数的乘积N = \({P_1}^{\alpha_1} {P_2}^{\alpha_2} ... {P_n}^{\alpha_n}\),
这里\(P_1<P_2<...<P_n\)且均为质数,其诸指数\(a_i\)是正整数。这样的分解称为N的标准分解式
vector<int> get_divisors(int x)
{
vector<int> res;
for (int i = 1; i <= x / i; i ++ )
if (x % i == 0)
{
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(), res.end());
return res;
}
对任意一个数N都可以写成:
N = \({P_1} ^ {\alpha_1} {P_2} ^ {\alpha_2} ... {P_k} ^ {\alpha_k}\)
对于他的任一约数d = \({P_1} ^ {\beta_1} {P_2} ^ {\beta_2} ... {P_k} ^ {\beta_k}\),\((0 \le \beta_i \le \alpha_i)\)只要指数\(\beta\)不同,d就不同
所以N的约数的个数实际就是\(\beta_1\) ~ \(\beta_k\)的取法个数,其实就是看\(\beta_k\)有多少组合方式,如\(\beta_k\)有(0~\(\alpha_k\))即\((\alpha_k + 1)\)种选法
整体N的选法即N的约数个数 = \((\alpha_1 + 1) (\alpha_2 + 1) ... (\alpha_k+1)\)个
先求\((a_1 a_2 ... a_n)\)的质因式分解结果
把\(a_1,a_2,...,a_n\)都分别分解,再把每一个数的指数累加到一起就可以了
假设先求出\(a_1\)的某一个质因子\(P_i ^ {\alpha_i}\),可以用一个Hash表或一个map将他存下来
如map[\(P_i\)] += \(\alpha_i\)就可以了,最后map就存储了整个乘积的指数和底数
约数个数就是所有指数+1在相乘
/**
* 给定n个数a_1到a_n,
* 求出a_1 * a_2 * ... *a_n的约数个数取模1e9+7
*/
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 110, mod = 1e9 + 7;
int main()
{
int n;
cin >> n;
unordered_map<int, int> primes;
while (n -- )
{
int x;
cin >> x;
for (int i = 2; i <= x / i; i ++ )
while (x % i == 0)
{
x /= i;
primes[i] ++ ;
}
if (x > 1) primes[x] ++ ; // 说明x是一个比较大的质因数,把他记录一下
}
LL res = 1;
for (auto p : primes) res = res * (p.second + 1) % mod;
cout << res << endl;
return 0;
}
N = \({P_1} ^ {\alpha_1} {P_2} ^ {\alpha_2} ... {P_k} ^ {\alpha_k}\)
约数之和 = \((P_1^0 + P_1 ^ 1 + ... + P_1 ^ {\alpha_1}) (P_2^0 + P_2 ^ 1 + ... + P_2 ^ {\alpha_2}) ... (P_k^0 + P_k ^ 1 + ... + P_k ^ {\alpha_k})\)
将上述式子用乘法分配律展开共有\((\alpha_1+1)(\alpha_2+1)...(\alpha_k+1)\)种选法
每一个展开的乘积都是\((P_1^{\beta_1} P_2^{\beta_2}...P_k^{\beta_k})\)的形式,\((0 \le \beta_k \le \alpha_k)\)
这里的每一项其实都是一个约数,所以他一共的个数就是约 数的个数,可以发现这个式子展开其实就是把所有约数加到一起了
如何求出\(P^0 + P^1 + ... P^\alpha\)呢?
方法有很多,可以初始令t = 1, 每次令t = p*t+1
第一次执行后t=\(p^2+p+1\)
执行a次后t=\(P^0 + P^1 + ... P^\alpha\)
/**
* 给定n个数a_1到a_n,
* 求出a_1 * a_2 * ... *a_n的约数之和取模1e9+7
*/
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 110, mod = 1e9 + 7;
int main()
{
int n;
cin >> n;
unordered_map<int, int> primes;
while (n -- )
{
int x;
cin >> x;
for (int i = 2; i <= x / i; i ++ )
while (x % i == 0)
{
x /= i;
primes[i] ++ ;
}
if (x > 1) primes[x] ++ ;
}
LL res = 1;
for (auto p : primes) // 枚举所有的质因数
{
LL a = p.first, b = p.second; // p是底数,a是指数
LL t = 1;
// 求出P^0+P^1+...+P^n
while (b -- ) t = (t * a + 1) % mod;
res = res * t % mod;
}
cout << res << endl;
return 0;
}
标签:个数 lin 质数 方式 iso 数论 简单 names 乘法
原文地址:https://www.cnblogs.com/ApStar/p/13904614.html