约数个数
算数基本定理:一个合数可以分解为质因数的乘积,如果无论顺序的话,那么此分解唯一。
约数个数定理:根据算数基本定理可以得到质因数,然后相同的质因数进行合并,然后根据约数定理我们可以知道
p(m) ^ a(m) :pm的am次方,它的约数个数有am+1个,又根据乘法定理得到n的约数个数就是(a1+1) * (a2 + 1) * …* (am + 1);
#include <iostream>
using namespace std;
int aaa(int n){
int count = 0,i;
for(i=1;i*i<n;i++){
if(n % i ==0){
count+=2;
}
}
if(i*i==n)count++;
return count;
}
int main(){
int n,m,count = 0;
while(cin>>n){
for(int i = 0;i < n;i++){
cin>>m;
cout<<aaa(m)<<endl;
}
}
return 0;
}
约数之和
约数和定理:就是求一个正整数的约数之和
由算数基本定理可知:n = p1^a1 * p2^a2 * p3^a3 * … * pm^am。
又由约数个数定理可知:d(n) = (a1+1) * (a2 + 1) * …* (am + 1)。
#include<iostream>
#include<unordered_map>
using namespace std;
const int mod = 1e9 + 7;
typedef long long LL;
int main()
{
int n;
cin >> n;
unordered_map<int, int>primes;
while (n--)
{
int x;
cin >> x;
//将每一个整数x都分解质因数
for (int i = 2; i <= x / i; i++)
{
while (x % i == 0)
{
primes[i]++;
x /= i;
}
}
if (x > 1)
primes[x]++;
}
LL res = 1;
for (auto it : primes)
{
LL p = it.first, a = it.second;
LL t = 1;
while (a--)
t = (t * p + 1) % mod;
res = res * t % mod;
}
cout << res << endl;
return 0;
}
最大公约数
1、辗转相除法
int gcd (int a, int b){
return b == 0 ? a :gcd(b, a%b);
}
//为了避免递归调用产生问题,所以我们使用循环来重写
//怎么将递归写成循环 //非递归版本
int gcd (int a, int b){
if(a < b) swap(a, b);
while( b != 0 ){ //或者写成!b
int tmp = a;
a = b;
b = temp % b; //相当于递归中的a % b
}
return a;
}
2、更相减损术
int gcd(int a, int b){
if(a < b) swap(a, b);
return b == 0 ? a : gcd(max(b, a - b), mix(b, a-b));
}
//非递归写法
int gcd(int a, int b){
if(a < b) swap(a, b);
while( !b ){
int tmp = a;
a = max(b, a - b);
b = min(b, a - b);
}
}
3、最小公倍数
和最大公约数有联系,两个数的最大公倍数等于两个数的乘积除以最大公约数。
3 7 =》3 * 7
既然公共的约数都被我们去掉了,那剩下的两个数肯定就不会有公共的约数
12 15 =》12 5 =》 4和15互质,那么这两个数的乘积就是最小公倍数
可能用到算术基本定理,组合数学,最大公约数,最小公倍数
12 和 15
12 = 2^2 * 3^1
15 = 3^1 * 5^1
//约掉最大公约数
//60是最小公倍数
60 = 3^1 * 2^2 * 5^1
3 = 3^1
12 = 3^1 * 2^2
15 = 3^1 * 5^1
假如我们最后求出来有n个素因数
那么这n个素因数都可以放任意一个数中
1 2 3 4 5 ... n
2 2 2 2 2 ... 2
2^n
2^2 * 5^1 = 60/3;
//所以它的这两个实际就是除去最大公约数的素因数的组合
//比如我想造一个最大公约数为12的数
根据算术基本定理,我知道素因数的分解一定是唯一的
所以我只需要每个数造12的素因数,剩下的数我随便写都会是最大公约数为12的数
2^2 * 3^1
2^2 * 3^1
接下来你就是想要这两个的最小公倍数是你给定的数
比如题目给的3 和 60
//又因为约掉最大公约数之后所有数的乘积就是最小公倍数
3^1 * 2^2 * 5^1
3^1
num1:
num2:
num1 * num2 = 60 / 3 = 20
2^2 5^1
2^2*5^1 1
接下来我们只需要找到那些素因数即可
3,60
15,12
2 * 2 * 3 * 5 = 60
180 = 2^2 * 3^2 * 5^1
75 = 3^1 * 5^2
相同的约数
然后算术基本定理告诉我们
一个合数的可以写成质因数的乘积的形式,并且次分解唯一
所以我们知道两个数的最大公约数就是质因数分解中相同质数的指数小的那一群的乘积 3^1 * 5^1
同样的,我们可以知道最小公倍数就是质因数分解中每个相同质数质数大的那一群的乘积 2^2 * 3^2 * 5^2