[英]Fast Prime Factorization Algorithm
我正在用 C 編寫一個代碼,它返回一個正整數可以表示為兩個正整數的完全平方和的次數。
R(n) is the number of couples (x,y) such that x² + y² = n where x, y, n are all
non negative integers.
為了計算 R(n),我需要首先找到 n 的質因數分解。
問題是我已經嘗試了很多可以在 C 上使用的素數分解算法,但我需要我的代碼盡可能快,所以如果有人能給我他/她認為是計算大到2147483742.
的數的質因數分解的最快算法2147483742.
多么奇怪的限制; 2147483742 = 2^31 + 94。
正如其他人指出的那樣,對於一個數字,這個由素數進行的小試除很可能足夠快。 如果不是,您可以嘗試 Pollard 的 rho 方法:
/* WARNING! UNTESTED CODE! */
long rho(n, c) {
long t = 2;
long h = 2;
long d = 1;
while (d == 1) {
t = (t*t + c) % n;
h = (h*h + c) % n;
h = (h*h + c) % n;
d = gcd(t-h, n); }
if (d == n)
return rho(n, c+1);
return d;
}
稱為rho(n,1)
此函數返回n的(可能是復合)因子; 如果您想找到n 的所有因子,請將其放入循環中並重復調用它。 你還需要一個素數檢查器; 對於您的極限,以 2、7 和 61 為基數的 Rabin-Miller 測試被證明是准確且相當快的。 您可以在我的博客上閱讀更多關於使用質數編程的信息。
但無論如何,鑒於如此小的限制,我認為您最好使用素數試除。 其他任何東西都可能漸近地更快,但實際上更慢。
編輯:這個答案最近收到了幾個贊成票,所以我添加了一個簡單的程序,用 2、3、5 輪進行輪分解。 該程序稱為wheel(n)
,按遞增順序打印n的因子。
long wheel(long n) {
long ws[] = {1,2,2,4,2,4,2,4,6,2,6};
long f = 2; int w = 0;
while (f * f <= n) {
if (n % f == 0) {
printf("%ld\n", f);
n /= f;
} else {
f += ws[w];
w = (w == 10) ? 3 : (w+1);
}
}
printf("%ld\n", n);
return 0;
}
我在 我的博客中討論了輪子分解; 解釋很長,所以我不會在這里重復。 對於適合long
整數,您不太可能顯着改善上面給出的wheel
函數。
有一種快速的方法可以減少候選人的數量。 此例程嘗試 2,然后是 3,然后是所有不能被 3 整除的奇數。
long mediumFactor(n)
{
if ((n % 2) == 0) return 2;
if ((n % 3) == 0) return 3;
try = 5;
inc = 2;
lim = sqrt(n);
while (try <= lim)
{
if ((n % try) == 0) return try;
try += inc;
inc = 6 - inc; // flip from 2 -> 4 -> 2
}
return 1; // n is prime
}
inc 在 2 和 4 之間的交替經過仔細對齊,以便跳過所有偶數和可被 3 整除的數。對於這種情況: 5 (+2) 7 (+4) 11 (+2) 13 (+4) 17
試驗在 sqrt(n) 處停止,因為至少有一個因子必須等於或低於平方根。 (如果兩個因子都 > sqrt(n),那么因子的乘積將大於 n。)
嘗試次數為 sqrt(m)/3,其中 m 是系列中可能的最高數字。 對於 2147483647 的限制,最壞情況下(對於 2147483647 附近的素數)最多產生 15,448 個除法,包括 2 和 3 測試。
如果數字是合數,則划分的總數通常要少得多,很少會更多; 甚至考慮到重復調用例程來獲取所有因素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.