pta 181 求因子和
c++格式化輸出
微秒級計時
素數篩演算法
因子和公式
直接使用sqrt(n)為迴圈上限的方法,時間穩定o(sqrt(n)),程式執行不會超時
素數篩法理論複雜度小於o(sqrt(n)),在因子遠小於n的情況下能達到最佳效果
由於演算法相對複雜,素數篩法的執行時間會更高
在大數區間[108,109]內隨機選取的平均運算時間是 素數篩: 開方法 ≈2: 1部分執行結果可見下圖,前4個數為比較有代表性的測試數字,最後為4中的平均時間
//開方法
intsumoffactor_sqrt
(int n )
return n % i? sum: sum+i;
}
然而素數篩法會在篩素數的過程消耗大量時間,在不優化的情況下其複雜度和開方法一樣都是o(sqrt(n)),優化思路落在了迴圈上限上。由於不需要求得每個因子的值,可以在求出每乙個素因子後讓n除去改素因子,通過降低n的值降低迴圈的次數。因此,根據上一段中關於最後乙個素數的判斷方法,設n的最大素因子為p,次數為q,則素數篩法理論時間複雜度為o( max( log(n), sqrt(pq) ) )
int
sumoffactor_sieve
(int n )
sum *
= v;
}for
(int j =
0; j < pcnt && i*primes[j]
<= n/i/primes[j]
; j++
) isnotprime[i*primes[j]]=
true;}
if( n >
1) sum *
=( n+1)
; sum -
= num;
return sum;
}
#include
#include
#include
#include
#include
#include
using
namespace std;
int primes[
100000];
int pcnt =0;
bool isnotprime[
100000]=
;void
decompose
(int n )
if(flag && c)
cout <<
" + ";if
(c)}
for(
int j =
0; j < pcnt && i*primes[j]
<= n/i/primes[j]
; j++
) isnotprime[i*primes[j]]=
true;}
if( n >1)
cout <<
" + "
<< n <<
"^"<<1;
cout << endl;
}int
sumoffactor_sieve
(int n )
sum *
= v;
}for
(int j =
0; j < pcnt && i*primes[j]
<= n/i/primes[j]
; j++
) isnotprime[i*primes[j]]=
true;}
if( n >
1) sum *
=( n+1)
; sum -
= num;
return sum;
}int
sumoffactor_sqrt
(int n )
intsumoffactor_sub2
(int n )
intmain()
; testlen =
sizeof
(testvalue)
/sizeof
(int);
cout <<
"一共 "
<< testlen <<
" 組測試資料"
<< endl;
cout << endl;
for(
int i =
0; i < testlen; i++)
rtime = rtime2 =0;
int rmax =
1000000000
;int rmin =
100000000
;int times =
10000
;for
(int i =
0; i < times; i++
) rtime /
= times;
rtime2 /
= times;
cout <<
"====平均用時==== "
; cout <<
"max = "
<< scientific <<
setprecision(2
)<<
(double
)rmax <<
", "
; cout <<
"min = "
<< scientific <<
setprecision(2
)<<
(double
)rmin <<
", "
; cout <<
"rounds = "
<< times;
cout << endl;
cout <<
setw(16
)<< left <<
"素數篩法"
<<
"用時 : "
; cout <<
setw(2
)<< rtime /
1000000
<<
"s "
; cout <<
setw(4
)<<
(rtime /
1000)%
1000
<<
"ms "
; cout <<
setw(4
)<< rtime %
1000
<<
"us"
<< endl;
cout <<
setw(16
)<< left <<
"開方法"
<<
"用時 : "
; cout <<
setw(2
)<< rtime2 /
1000000
<<
"s "
; cout <<
setw(4
)<<
(rtime2 /
1000)%
1000
<<
"ms "
; cout <<
setw(4
)<< rtime2 %
1000
<<
"us"
<< endl;
return0;
}
素數的篩法
素數的篩法有很多種 在此給出常見的三種方法 以下給出的所有 均已通過這裡的測試 名字好長 joy 不過 很短 思路非常簡單,對於每乙個素數,列舉它的倍數,它的倍數一定不是素數 這樣一定可以保證每個素數都會被篩出來 還有,我們第一層迴圈列舉到 sqrt n 就好,因為如果當前列舉的數大於n,那麼它能篩...
改進的篩素數法
最簡單的篩素數法方法就是從2開始,將所以2的倍數去掉,然後從3開始,將3的倍數去掉。根據這樣很容易寫出 下面 就是是篩素數法得到100以內的素數並儲存到primes陣列中。cpp view plain copy by morewindows const intmaxn 100 bool flag m...
改進的篩素數法
最簡單的篩素數法方法就是從2開始,將所以2的倍數去掉,然後從3開始,將3的倍數去掉。根據這樣很容易寫出 下面 就是是篩素數法得到100以內的素數並儲存到primes陣列中。const int maxn 100 bool flag maxn int primes maxn 3 pi void getp...