算术基本定理Fundamental Theorem of Arithmetic
凡是正整数都可以藉由质因数分解成为一个独一无二的式子,不同的n 就会对应不同的(n1, n2, … ) ,反方向亦同。
根据算术基本定理,凡是牵扯到乘法、因数、倍数的数学运算,都可以改变成比较简单的运算。
分解前| 分解后
n | (n1, n2, ...)
m | (m1, m2, ...)
-----------+--------------------------------------
乘除法| 加减法
n × m | (n1 + m1, n2 + m2, ...)
n ÷ m | (n1 - m1, n2 - m2, ...)
|
整除| 大于等于
n % m = 0 | (n1, n2, ...) ≥ (m1, m2, ...)
m | n | n1≥m1 and n2≥m2 and ...
|
最大公因数| 最小值
gcd(n, m) | (min(n1, m1), min(n2, m2), ...)
|
最小公倍数| 最大值
lcm(n, m) | (max(n1, m1), max(n2, m2), ...)
|
互质| 对应项必须有零
n⊥m | min(n1, m1) = 0 and min(n2, m2) = 0 and ...
把一个数字分解成两个数的乘积(这两个数不一定是质数)。一直递回分解下去,无法再分解的时候就找到质因数了。分解手法如下:
现在要找出a 和b 让n = a*b
运用平方差公式x^2 – y^2 = (x+y) * (xy)
令n = x^2 – y^2, a = x+y, b = xy
穷举整数x,看看sqrt(x^2-n) 是不是刚好就是一个整数y,
如果是整数就找到一组a 和b 了。
凡是正整数都可以藉由质因数分解成为一个独一无二的式子,不同的n 就会对应不同的(n1, n2, … ) ,反方向亦同。
根据算术基本定理,凡是牵扯到乘法、因数、倍数的数学运算,都可以改变成比较简单的运算。
分解前| 分解后
n | (n1, n2, ...)
m | (m1, m2, ...)
-----------+--------------------------------------
乘除法| 加减法
n × m | (n1 + m1, n2 + m2, ...)
n ÷ m | (n1 - m1, n2 - m2, ...)
|
整除| 大于等于
n % m = 0 | (n1, n2, ...) ≥ (m1, m2, ...)
m | n | n1≥m1 and n2≥m2 and ...
|
最大公因数| 最小值
gcd(n, m) | (min(n1, m1), min(n2, m2), ...)
|
最小公倍数| 最大值
lcm(n, m) | (max(n1, m1), max(n2, m2), ...)
|
互质| 对应项必须有零
n⊥m | min(n1, m1) = 0 and min(n2, m2) = 0 and ...
| n1*m1 = 0 and n2*m2 = 0 and ...
把所有可能的因数拿来试除。用质因数会更好;可以预先建立质数表。
void trial_division ( int n )
{
// 穷举所有可能的因数,一一试除。
for ( int d = 2 ; d <= n ; ++ d )
while ( n % d == 0 )
{
n / = d ;
cout << d ; //印出质因数
}
}
void trial_division ( int n )
{
// 一个数字n不会有大于sqrt(n)的质因数(除了n本身以外)
int sqrt_n = sqrt ( n );
for ( int d = 2 ; d <= sqrt_n ; ++ d )
while ( n % d == 0 )
{
n / = d ;
cout << d ; //印出质因数
}
if ( n > 1 ) cout << n ; // n是质数
}
把一个数字分解成两个数的乘积(这两个数不一定是质数)。一直递回分解下去,无法再分解的时候就找到质因数了。分解手法如下:
现在要找出a 和b 让n = a*b
运用平方差公式x^2 – y^2 = (x+y) * (xy)
令n = x^2 – y^2, a = x+y, b = xy
穷举整数x,看看sqrt(x^2-n) 是不是刚好就是一个整数y,
如果是整数就找到一组a 和b 了。
void fermat ( int n )
{
for ( int x = sqrt ( n ); x < n ; ++ x )
{
int yy = x * x – n , y = sqrt ( yy );
if ( y * y == yy ) //如果sqrt(x^2-n)是整数
{
int a = x + y , b = x – y ;
cout << "n =" << a << "*" << b ;
// 递回分解a和b,继续质因数分解。
fermat ( a ); fermat ( b );
}
}
}