给定数字N ,任务是找到N的因数。
例子:
Input: N = 1000009
Output: 293 3413
Explanation:
293 * 3413 = 1000009
Input: N = 100000
Output: 800 125
Explanation:
800 * 125 = 100000
欧拉因式分解方法:欧拉因式分解方法的原理是,可以将以两种不同方式写为两个幂的和的所有数字N可以分解为两个数字,即N = A 2 + B 2 = C 2 + D 2 ,其中A!= C和A!= D,则对于N存在两个因素。
算法的工作:令N为我们需要查找因子的数字。
- 因此,最初,我们需要找到两种方式将N表示为两个数字的幂的和。
N = A2 + B2
N = C2 + D2
Therefore,
N = A2 + B2 = C2 + D2
- 现在,对上述方程式执行代数运算,以将方程式转换为:
N = A2 + B2 = C2 + D2
-> N = A2 - C2 = D2 - B2
-> N = (A - C)(A + C) = (D - B)(D + B)
- 令K为(A – C)和(D – B)的GCD。所以,
A - C = K * L
D - B = K * M
where GCD(L, M) is 1.
- 显然,L =(A – C)/ K,M =(D – B)/ K。将其代入初始方程式时:
N = K * L * (A + C) = K * M * (D + B)
-> L * (A + C) = M * (D + B)
->l (A + C)/(D + B) = M/L
- 所以:
(A + C) = M * H
(D + B) = L * H
where,
H = gcd((A + C), (D + B))
- 令Q =(K 2 + H 2 )(L 2 + M 2 )。
-> ((KL)2 + (KM)2 + (HL)2 + (HM)2)
-> ((A - C)2 + (D - B)2 + (D + B)2 + (A + C)2)
-> ((2 * A)2 + (2 * B)2 + (2 * C)2 + (2 * D)2)
-> 4 * N
- 所以,
N = ((K/2)2 + (H/2)2)(L2 + M2)
- 这样就存在一对K和H,它们都是偶数。
让我们通过一个例子来形象化上述方法。令N = 221。
- 221 = 11 2 + 10 2 = 5 2 + 14 2
- 根据以上公式:
A = 11 - 5 = 6
B = 11 + 5 = 15
C = 14 - 10 = 4
D = 14 + 10 = 24
- 因此,以上值可用于计算K,H,L和M的值。
K = GCD(6, 4) = 2
H = GCD(16, 24) = 8
L = GCD(6, 24) = 3
M = GCD(16, 4) = 2
- 所以:
221 = ((2/2)2 + (8/2)2) * (32 + 22)
221 = 17 * 13
方法:为了实现上述方法,需要执行以下步骤:
- 通过迭代从1到sqrt(N)的循环来求平方和,因为[sqrt(N),N]之间不存在除N之外的因子,并找到两对平方和等于N的对。
- 将值存储在A,B,C,D中。
- 使用上述方法中提到的公式找到K,H,L和M的值。
- 使用K,H,L和M的值查找因素。检查两个数字均是偶数的对,并将它们对半除,然后找出因子。
下面是上述方法的实现:
C++
// C++ program to implement Eulers
// Factorization algorithm
#include
using namespace std;
// Function to return N as the sum of
// two squares in two possible ways
void sumOfSquares(int n, vector >& vp)
{
// Iterate a loop from 1 to sqrt(n)
for (int i = 1; i <= sqrt(n); i++) {
// If i*i is square check if there
// exists another integer such that
// h is a perfect square and i*i + h = n
int h = n - i * i, h1 = sqrt(h);
// If h is perfect square
if (h1 * h1 == h) {
// Store in the sorted way
int a = max(h1, i), b = min(h1, i);
// If there is already a pair
// check if pairs are equal or not
if (vp.size() == 1 && a != vp[0].first)
vp.push_back(make_pair(a, b));
// Insert the first pair
if (vp.size() == 0)
vp.push_back(make_pair(a, b));
// If two pairs are found
if (vp.size() == 2)
return;
}
}
}
// Function to find the factors
void findFactors(int n)
{
// Get pairs where a^2 + b^2 = n
vector > vp;
sumOfSquares(n, vp);
// Number cannot be represented
// as sum of squares in two ways
if (vp.size() != 2)
cout << "Factors Not Possible";
// Assign a, b, c, d
int a, b, c, d;
a = vp[0].first;
b = vp[0].second;
c = vp[1].first;
d = vp[1].second;
// Swap if a < c because
// if a - c < 0,
// GCD cant be computed.
if (a < c) {
int t = a;
a = c;
c = t;
t = b;
b = d;
d = t;
}
// Compute the values of k, h, l, m
// using the formula mentioned
// in the approach
int k, h, l, m;
k = __gcd(a - c, d - b);
h = __gcd(a + c, d + b);
l = (a - c) / k;
m = (d - b) / k;
// Print the values of a, b, c, d
// and k, l, m, h
cout << "a = " << a
<< "\t\t(A) a - c = " << (a - c)
<< "\t\tk = gcd[A, C] = "
<< k << endl;
cout << "b = " << b
<< "\t\t(B) a + c = " << (a + c)
<< "\t\th = gcd[B, D] = "
<< h << endl;
cout << "c = " << c
<< "\t\t(C) d - b = " << (d - b)
<< "\t\tl = A/k = "
<< l << endl;
cout << "d = " << d
<< "\t\t(D) d + b = " << (d + b)
<< "\t\tm = c/k = "
<< m << endl;
// Printing the factors
if (k % 2 == 0 && h % 2 == 0) {
k = k / 2;
h = h / 2;
cout << "Factors are: "
<< ((k) * (k) + (h) * (h))
<< " " << (l * l + m * m)
<< endl;
}
else {
l = l / 2;
m = m / 2;
cout << "Factors are: "
<< ((l) * (l) + (m) * (m))
<< " " << (k * k + h * h)
<< endl;
}
}
// Driver code
int main()
{
int n = 100000;
findFactors(n);
return 0;
}
Java
// Java program to implement Eulers
// Factorization algorithm
import java.util.*;
class GFG{
static class pair
{
int first, second;
public pair(int first,
int second)
{
this.first = first;
this.second = second;
}
}
// Recursive function to
// return gcd of a and b
static int __gcd(int a, int b)
{
return b == 0 ? a :
__gcd(b, a % b);
}
// Function to return N as the sum of
// two squares in two possible ways
static void sumOfSquares(int n,
Vector vp)
{
// Iterate a loop from 1 to Math.sqrt(n)
for (int i = 1; i <= Math.sqrt(n); i++)
{
// If i*i is square check if there
// exists another integer such that
// h is a perfect square and i*i + h = n
int h = n - i * i, h1 = (int)Math.sqrt(h);
// If h is perfect square
if (h1 * h1 == h)
{
// Store in the sorted way
int a = Math.max(h1, i),
b = Math.min(h1, i);
// If there is already a pair
// check if pairs are equal or not
if (vp.size() == 1 &&
a != vp.get(0).first)
vp.add(new pair(a, b));
// Insert the first pair
if (vp.size() == 0)
vp.add(new pair(a, b));
// If two pairs are found
if (vp.size() == 2)
return;
}
}
}
// Function to find the factors
static void findFactors(int n)
{
// Get pairs where a^2 + b^2 = n
Vector vp = new Vector<>();
sumOfSquares(n, vp);
// Number cannot be represented
// as sum of squares in two ways
if (vp.size() != 2)
System.out.print("Factors Not Possible");
// Assign a, b, c, d
int a, b, c, d;
a = vp.get(0).first;
b = vp.get(0).second;
c = vp.get(1).first;
d = vp.get(1).second;
// Swap if a < c because
// if a - c < 0,
// GCD cant be computed.
if (a < c)
{
int t = a;
a = c;
c = t;
t = b;
b = d;
d = t;
}
// Compute the values of k, h, l, m
// using the formula mentioned
// in the approach
int k, h, l, m;
k = __gcd(a - c, d - b);
h = __gcd(a + c, d + b);
l = (a - c) / k;
m = (d - b) / k;
// Print the values of a, b, c, d
// and k, l, m, h
System.out.print("a = " + a +
"\t\t(A) a - c = " +
(a - c) +
"\t\tk = gcd[A, C] = " +
k + "\n");
System.out.print("b = " + b +
"\t\t(B) a + c = " +
(a + c) +
"\t\th = gcd[B, D] = " +
h + "\n");
System.out.print("c = " + c +
"\t\t(C) d - b = " +
(d - b) +
"\t\tl = A/k = " +
l + "\n");
System.out.print("d = " + d +
"\t\t(D) d + b = " +
(d + b) +
"\t\tm = c/k = " +
m + "\n");
// Printing the factors
if (k % 2 == 0 && h % 2 == 0)
{
k = k / 2;
h = h / 2;
System.out.print("Factors are: " +
((k) * (k) + (h) * (h)) +
" " + (l * l + m * m) + "\n");
}
else
{
l = l / 2;
m = m / 2;
System.out.print("Factors are: " +
((l) * (l) + (m) * (m)) +
" " + (k * k + h * h) + "\n");
}
}
// Driver code
public static void main(String[] args)
{
int n = 100000;
findFactors(n);
}
}
// This code is contributed by gauravrajput1
C#
// C# program to implement Eulers
// Factorization algorithm
using System;
using System.Collections.Generic;
class GFG{
public class pair
{
public int first, second;
public pair(int first,
int second)
{
this.first = first;
this.second = second;
}
}
// Recursive function to
// return gcd of a and b
static int __gcd(int a, int b)
{
return b == 0 ? a :
__gcd(b, a % b);
}
// Function to return N as the sum of
// two squares in two possible ways
static void sumOfSquares(int n,
List vp)
{
// Iterate a loop from 1 to Math.Sqrt(n)
for (int i = 1; i <= Math.Sqrt(n); i++)
{
// If i*i is square check if there
// exists another integer such that
// h is a perfect square and i*i + h = n
int h = n - i * i, h1 = (int)Math.Sqrt(h);
// If h is perfect square
if (h1 * h1 == h)
{
// Store in the sorted way
int a = Math.Max(h1, i),
b = Math.Min(h1, i);
// If there is already a pair
// check if pairs are equal or not
if (vp.Count == 1 &&
a != vp[0].first)
vp.Add(new pair(a, b));
// Insert the first pair
if (vp.Count == 0)
vp.Add(new pair(a, b));
// If two pairs are found
if (vp.Count == 2)
return;
}
}
}
// Function to find the factors
static void findFactors(int n)
{
// Get pairs where a^2 + b^2 = n
List vp = new List();
sumOfSquares(n, vp);
// Number cannot be represented
// as sum of squares in two ways
if (vp.Count != 2)
Console.Write("Factors Not Possible");
// Assign a, b, c, d
int a, b, c, d;
a = vp[0].first;
b = vp[0].second;
c = vp[1].first;
d = vp[1].second;
// Swap if a < c because
// if a - c < 0,
// GCD cant be computed.
if (a < c)
{
int t = a;
a = c;
c = t;
t = b;
b = d;
d = t;
}
// Compute the values of k, h, l, m
// using the formula mentioned
// in the approach
int k, h, l, m;
k = __gcd(a - c, d - b);
h = __gcd(a + c, d + b);
l = (a - c) / k;
m = (d - b) / k;
// Print the values of a, b, c, d
// and k, l, m, h
Console.Write("a = " + a +
"\t\t(A) a - c = " +
(a - c) +
"\t\tk = gcd[A, C] = " +
k + "\n");
Console.Write("b = " + b +
"\t\t(B) a + c = " +
(a + c) +
"\t\th = gcd[B, D] = " +
h + "\n");
Console.Write("c = " + c +
"\t\t(C) d - b = " +
(d - b) +
"\t\tl = A/k = " +
l + "\n");
Console.Write("d = " + d +
"\t\t(D) d + b = " +
(d + b) +
"\t\tm = c/k = " +
m + "\n");
// Printing the factors
if (k % 2 == 0 && h % 2 == 0)
{
k = k / 2;
h = h / 2;
Console.Write("Factors are: " +
((k) * (k) + (h) * (h)) +
" " + (l * l + m * m) + "\n");
}
else
{
l = l / 2;
m = m / 2;
Console.Write("Factors are: " +
((l) * (l) + (m) * (m)) +
" " + (k * k + h * h) + "\n");
}
}
// Driver code
public static void Main(String[] args)
{
int n = 100000;
findFactors(n);
}
}
// This code is contributed by gauravrajput1
输出:
a = 316 (A) a - c = 16 k = gcd[A, C] = 8
b = 12 (B) a + c = 616 h = gcd[B, D] = 56
c = 300 (C) d - b = 88 l = A/k = 2
d = 100 (D) d + b = 112 m = c/k = 11
Factors are: 800 125
复杂度分析:
时间复杂度: O(sqrt(N)) ,其中N是给定的数字
空间复杂度: O(1)