给定一个正整数 N ,并且它是复合的,找到它的一个除数。 例子:
Input: n = 12;Output: 2 [OR 3 OR 4]Input: n = 187;Output: 11 [OR 17]
粗暴的做法: 测试所有小于n的整数,直到找到一个除数。 即兴创作: 测试所有小于的整数√N 足够大的数量仍然意味着大量的工作。 波拉德氏Rho 是一种素因式分解算法,对于具有小素因式的大合数特别快。Rho算法最显著的成功是第八个费马数的因式分解:1238926361552897*9346163977769163558199606896584051237541638188580280321。 Rho算法是一个很好的选择,因为第一个素因子比另一个小得多。 Pollard的Rho算法中使用的概念:
- 如果
- 它们的绝对差是n的整数倍,
- 当它们被n除时,每一个都留下相同的余数。
- 这个 最大公约数 是平均分成每个原始数的最大数。
- 生日悖论: 即使是对一小部分人来说,两个人生日相同的概率也出人意料地高。
- Floyd的循环查找算法: 如果乌龟和兔子在同一点出发,在一个循环中移动,兔子的速度是乌龟速度的两倍,那么它们必须在某个点相遇。
算法 :
- 从随机x和c开始。取y等于x,f(x)=x 2. +c。
- 而除数是不存在的
- 将x更新为f(x)(模n)[乌龟移动]
- 将y更新为f(f(y))(模n)[兔子移动]
- 计算| x-y |和n的GCD
- 如果GCD不是统一的
- 如果GCD为n,用另一组x、y和c重复步骤2
- 否则GCD就是我们的答案
插图: 让我们假设一下 n=187 针对不同的随机值考虑不同的情况。
- 一个随机值的例子,比如 找到结果 : y=x=2,c=1,因此我们的f(x)=x 2. + 1.
- 一个随机值的例子,比如 更快地找到结果 : y=x=110,c=183。因此,我们的f(x)=x 2. + 183.
- 一个随机值的例子,比如 找不到结果 : x=y=147,c=67。因此,我们的f(x)=x 2. + 67.
下面是上述算法的C/C++实现:
C++
/* C++ program to find a prime factor of composite using Pollard's Rho algorithm */ #include<bits/stdc++.h> using namespace std; /* Function to calculate (base^exponent)%modulus */ long long int modular_pow( long long int base, int exponent, long long int modulus) { /* initialize result */ long long int result = 1; while (exponent > 0) { /* if y is odd, multiply base with result */ if (exponent & 1) result = (result * base) % modulus; /* exponent = exponent/2 */ exponent = exponent >> 1; /* base = base * base */ base = (base * base) % modulus; } return result; } /* method to return prime divisor for n */ long long int PollardRho( long long int n) { /* initialize random seed */ srand ( time (NULL)); /* no prime divisor for 1 */ if (n==1) return n; /* even number means one of the divisors is 2 */ if (n % 2 == 0) return 2; /* we will pick from the range [2, N) */ long long int x = ( rand ()%(n-2))+2; long long int y = x; /* the constant in f(x). * Algorithm can be re-run with a different c * if it throws failure for a composite. */ long long int c = ( rand ()%(n-1))+1; /* Initialize candidate divisor (or result) */ long long int d = 1; /* until the prime factor isn't obtained. If n is prime, return n */ while (d==1) { /* Tortoise Move: x(i+1) = f(x(i)) */ x = (modular_pow(x, 2, n) + c + n)%n; /* Hare Move: y(i+1) = f(f(y(i))) */ y = (modular_pow(y, 2, n) + c + n)%n; y = (modular_pow(y, 2, n) + c + n)%n; /* check gcd of |x-y| and n */ d = __gcd( abs (x-y), n); /* retry if the algorithm fails to find prime factor * with chosen x and c */ if (d==n) return PollardRho(n); } return d; } /* driver function */ int main() { long long int n = 10967535067; printf ( "One of the divisors for %lld is %lld." , n, PollardRho(n)); return 0; } |
JAVA
/* Java program to find a prime factor of composite using Pollard's Rho algorithm */ import java.util.*; class GFG{ /* Function to calculate (base^exponent)%modulus */ static long modular_pow( long base, int exponent, long modulus) { /* initialize result */ long result = 1 ; while (exponent > 0 ) { /* if y is odd, multiply base with result */ if (exponent % 2 == 1 ) result = (result * base) % modulus; /* exponent = exponent/2 */ exponent = exponent >> 1 ; /* base = base * base */ base = (base * base) % modulus; } return result; } /* method to return prime divisor for n */ static long PollardRho( long n) { /* initialize random seed */ Random rand = new Random(); /* no prime divisor for 1 */ if (n == 1 ) return n; /* even number means one of the divisors is 2 */ if (n % 2 == 0 ) return 2 ; /* we will pick from the range [2, N) */ long x = ( long )(rand.nextLong() % (n - 2 )) + 2 ; long y = x; /* the constant in f(x). * Algorithm can be re-run with a different c * if it throws failure for a composite. */ long c = ( long )(rand.nextLong()) % (n - 1 ) + 1 ; /* Initialize candidate divisor (or result) */ long d = 1L; /* until the prime factor isn't obtained. If n is prime, return n */ while (d == 1 ) { /* Tortoise Move: x(i+1) = f(x(i)) */ x = (modular_pow(x, 2 , n) + c + n) % n; /* Hare Move: y(i+1) = f(f(y(i))) */ y = (modular_pow(y, 2 , n) + c + n) % n; y = (modular_pow(y, 2 , n) + c + n) % n; /* check gcd of |x-y| and n */ d = __gcd(Math.abs(x - y), n); /* retry if the algorithm fails to find prime factor * with chosen x and c */ if (d == n) return PollardRho(n); } return d; } // Recursive function to return gcd of a and b static long __gcd( long a, long b) { return b == 0 ? a:__gcd(b, a % b); } /* driver function */ public static void main(String[] args) { long n = 10967535067L; System.out.printf( "One of the divisors for " + n + " is " + PollardRho(n)); } } // This code contributed by aashish1995 |
Python3
# Python 3 program to find a prime factor of composite using # Pollard's Rho algorithm import random import math # Function to calculate (base^exponent)%modulus def modular_pow(base, exponent,modulus): # initialize result result = 1 while (exponent > 0 ): # if y is odd, multiply base with result if (exponent & 1 ): result = (result * base) % modulus # exponent = exponent/2 exponent = exponent >> 1 # base = base * base base = (base * base) % modulus return result # method to return prime divisor for n def PollardRho( n): # no prime divisor for 1 if (n = = 1 ): return n # even number means one of the divisors is 2 if (n % 2 = = 0 ): return 2 # we will pick from the range [2, N) x = (random.randint( 0 , 2 ) % (n - 2 )) y = x # the constant in f(x). # Algorithm can be re-run with a different c # if it throws failure for a composite. c = (random.randint( 0 , 1 ) % (n - 1 )) # Initialize candidate divisor (or result) d = 1 # until the prime factor isn't obtained. # If n is prime, return n while (d = = 1 ): # Tortoise Move: x(i+1) = f(x(i)) x = (modular_pow(x, 2 , n) + c + n) % n # Hare Move: y(i+1) = f(f(y(i))) y = (modular_pow(y, 2 , n) + c + n) % n y = (modular_pow(y, 2 , n) + c + n) % n # check gcd of |x-y| and n d = math.gcd( abs (x - y), n) # retry if the algorithm fails to find prime factor # with chosen x and c if (d = = n): return PollardRho(n) return d # Driver function if __name__ = = "__main__" : n = 10967535067 print ( "One of the divisors for" , n , "is " ,PollardRho(n)) # This code is contributed by chitranayal |
C#
/* C# program to find a prime factor of composite using Pollard's Rho algorithm */ using System; class GFG { /* Function to calculate (base^exponent)%modulus */ static long modular_pow( long _base, int exponent, long modulus) { /* initialize result */ long result = 1; while (exponent > 0) { /* if y is odd, multiply base with result */ if (exponent % 2 == 1) result = (result * _base) % modulus; /* exponent = exponent/2 */ exponent = exponent >> 1; /* base = base * base */ _base = (_base * _base) % modulus; } return result; } /* method to return prime divisor for n */ static long PollardRho( long n) { /* initialize random seed */ Random rand = new Random(); /* no prime divisor for 1 */ if (n == 1) return n; /* even number means one of the divisors is 2 */ if (n % 2 == 0) return 2; /* we will pick from the range [2, N) */ long x = ( long )(rand.Next(0, -( int )n + 1)); long y = x; /* the constant in f(x). * Algorithm can be re-run with a different c * if it throws failure for a composite. */ long c = ( long )(rand.Next(1, -( int )n)); /* Initialize candidate divisor (or result) */ long d = 1L; /* until the prime factor isn't obtained. If n is prime, return n */ while (d == 1) { /* Tortoise Move: x(i+1) = f(x(i)) */ x = (modular_pow(x, 2, n) + c + n) % n; /* Hare Move: y(i+1) = f(f(y(i))) */ y = (modular_pow(y, 2, n) + c + n) % n; y = (modular_pow(y, 2, n) + c + n) % n; /* check gcd of |x-y| and n */ d = __gcd(Math.Abs(x - y), n); /* retry if the algorithm fails to find prime factor * with chosen x and c */ if (d == n) return PollardRho(n); } return d; } // Recursive function to return gcd of a and b static long __gcd( long a, long b) { return b == 0 ? a:__gcd(b, a % b); } /* Driver code */ public static void Main(String[] args) { long n = 10967535067L; Console.Write( "One of the divisors for " + n + " is " + PollardRho(n)); } } // This code is contributed by aashish1995 |
Javascript
<script> /* Javascript program to find a prime factor of composite using Pollard's Rho algorithm */ /* Function to calculate (base^exponent)%modulus */ function modular_pow(base,exponent,modulus) { /* initialize result */ let result = 1; while (exponent > 0) { /* if y is odd, multiply base with result */ if (exponent % 2 == 1) result = (result * base) % modulus; /* exponent = exponent/2 */ exponent = exponent >> 1; /* base = base * base */ base = (base * base) % modulus; } return result; } /* method to return prime divisor for n */ function PollardRho(n) { /* no prime divisor for 1 */ if (n == 1) return n; /* even number means one of the divisors is 2 */ if (n % 2 == 0) return 2; /* we will pick from the range [2, N) */ let x=(Math.floor(Math.random() * (-n + 1) )); let y = x; /* the constant in f(x). * Algorithm can be re-run with a different c * if it throws failure for a composite. */ let c= (Math.floor(Math.random() * (-n + 1))); /* Initialize candidate divisor (or result) */ let d=1; /* until the prime factor isn't obtained. If n is prime, return n */ while (d == 1) { /* Tortoise Move: x(i+1) = f(x(i)) */ x = (modular_pow(x, 2, n) + c + n) % n; /* Hare Move: y(i+1) = f(f(y(i))) */ y = (modular_pow(y, 2, n) + c + n) % n; y = (modular_pow(y, 2, n) + c + n) % n; /* check gcd of |x-y| and n */ d = __gcd(Math.abs(x - y), n); /* retry if the algorithm fails to find prime factor * with chosen x and c */ if (d == n) return PollardRho(n); } return d; } // Recursive function to return gcd of a and b function __gcd(a,b) { return b == 0? a:__gcd(b, a % b); } /* driver function */ let n = 10967535067; document.write( "One of the divisors for " + n + " is " + PollardRho(n)); // This code is contributed by avanitrachhadiya2155 </script> |
输出:
One of the divisors for 10967535067 is 104729
这是怎么回事? 允许 n是复合(非素数) 因为n是复合的,所以它有一个非平凡的因子 F
- 算法将无限期地运行素数。
- 该算法可能无法找到因子并返回复合n的失败。在这种情况下,我们使用不同的x、y和c集,然后重试。
- 上述算法只找到一个除数。为了找到主要因素,我们可以 递归分解 除数d,d和n/d的运行算法。循环长度通常为√D
时间复杂性分析: 该算法在运行时间和找到因子的概率之间进行权衡。素数因子的概率约为0.5,单位为O(√d) <=O(n) 1/4 )迭代。这是一个启发性的主张,对算法的严格分析仍然是开放的。 本文由 亚什·瓦里亚尼 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论