约数相关知识
最大公约数
欧几里得算法(辗转相除法)
核心思想: GCD(a, b)<=> GCD(b, a % b)
证明: 略
结束条件: GCD(a, 0) 是 a
#include <iostream>
using namespace std;
//辗转相除法求最大公约数
// (a,b) <=> (b, a % b)
// LOG(N)
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
int n;
scanf("%d", &n);
while(n --)
{
int a, b;
scanf("%d%d", &a,&b);
printf("%d\n",gcd(a,b));
}
return 0;
}
约数总个数
相关知识点: 一个整数具有唯一形式的质因数分解式
N 可表示为 p1^c1 * p2^c2 * … *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * … * (ck + 1)
例题
给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 10^9+7
取模。
输入格式
第一行包含整数 n。
接下来 n行,每行包含一个整数 ai
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需取模。
数据范围
1≤n≤100,1≤ai≤2×10^9
输入样例:
3
2
6
8
输出样例:
12
#include <iostream>
#include <algorithm>
#include <unordered_map>
//equal hash table
using namespace std;
typedef long long LL;
const int 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 prime : primes)
res = res * (prime.second + 1) % mod;
cout << res << endl;
return 0;
}
所有约数和
约数总和公式:
( p1^0 + p1^1 +…+ p1^c1) mul…mul (pk^0 + pk^1 +…+ pk^ck)
例题
给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 10^9+7取模。
输入格式
第一行包含整数 n
接下来 n行,每行包含一个整数 ai
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 10^9+7
取模。
数据范围
1≤n≤100,1≤ai≤2×10^9
输入样例:
3
2
6
8
输出样例:
252
#include <iostream>
#include <algorithm>
#include <unordered_map>
//equal hash table
//求约数和
using namespace std;
typedef long long LL;
const int 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 ans = 1;
for(auto prime : primes)
{
int p = prime.first;
int a = prime.second;//index
LL t = 1;
//约数和公式
while(a --) t = (t * p + 1) % mod;
ans = (ans * t) % mod;
}
cout << ans << endl;
return 0;
}
试除法求所有约数
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> get_divisors(int n)
{
vector<int> res;
for(int i = 1; i <= n / i; i ++)
if(n % i == 0)
{
res.push_back(i);
if(i != n / i) res.push_back(n / i);
}
sort(res.begin(),res.end());
return res;
}
int main()
{
int n;
cin >> n;
while(n --)
{
int x;
cin >> x;
auto res = get_divisors(x);//get 约数
for(auto t : res) cout << t << ' ';
cout << endl;
}
return 0;
}