Comment detail
Meertens数 (Nested Flatten)This comment is reply for 4872 ところてん: とりあえず、再帰で書いてみた。 sea...(Meertens数). Go to thread root.
一応手元で11桁まで回り終わりましたが、 一桁増えると計算時間も10倍になりました。 (当然と言えば当然ですが) なので、google先生に聞いたところ、20桁では (176 * (10^10)) *秒 = 55 772.2258 年 だそうです。
とりあえず40秒くらいまで縮まったけど、 他の人が何で爆速なのかが分からない。 あとどんな枝狩りすりゃいいねん。 枝狩りで分岐予測がこける関係で、Pen4系では遅いと思う。 関数型言語は読めないよ・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include <stdio.h>
#include <time.h>
int primes[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
void _searchMeertens(int keta, int count, unsigned long long int r, unsigned long long int n){
int x;
n *= 10;
for(x = (count == 0); x < 10; x++){
if (x){
r *= primes[count];
n++;
}
if (keta == 0){
if(r > n){ //枝狩り
return;
}
else if (r == n){
printf("Found Meertens %d\n",n);
}
}else{
_searchMeertens(keta -1, count +1, r, n);
}
}
}
void searchMeertens(int keta)
{
int x;
time_t t;
t = time(NULL);
for(x = 0; x < keta; x++){
_searchMeertens(x,0,1,0);
printf("keta = %d time = %d\n", x+1, time(NULL) - t);
t = time(NULL);
}
}
int main(void)
{
int keta;
time_t t;
keta = 10;
t = time(NULL);
searchMeertens(keta);
printf("%dsec\n", time(NULL)-t);
printf("push anykey to exit.");
getchar();
}
|
r が、その桁の最大値を超えたときを狩れば結構削れますよ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | void _searchMeertens(int keta, int count, unsigned long long int r, unsigned long long int n, unsigned long long int nmax)
{
int x;
n *= 10;
for (x = (count == 0); x < 10; x++) {
if (x) {
r *= primes[count];
if (r > nmax) /* 枝狩り2 */
return;
n++;
}
if (keta == 0) {
if(r > n) /* 枝狩り*/
return;
if (r == n)
printf("Found Meertens %d\n", n);
}else{
_searchMeertens(keta -1, count + 1, r, n, nmax);
}
}
}
void searchMeertens(int keta)
{
int x;
unsigned long long int nmax;
time_t t;
t = time(NULL);
for (x = 0; x < keta; x++) {
nmax = (unsigned long long)pow(10.0, x + 1) - 1UL;
_searchMeertens(x, 0, 1, 0, nmax);
printf("keta = %d time = %d\n", x + 1, time(NULL) - t);
t = time(NULL);
}
}
|
なるほどなーと納得しました。 手元の奴で10桁が1秒未満で完了した・・・。 確かにそうすればよかったのかと後悔してます。 ちなみに私の環境での実行結果。 あまり時間が無かったので、18桁まで実行させましたが、20桁は20分くらいですね。 なのでトータルタイムは30分くらいでしょうか。 keta = 1 time = 0 keta = 2 time = 0 keta = 3 time = 0 keta = 4 time = 0 keta = 5 time = 0 keta = 6 time = 0 keta = 7 time = 0 Found Meertens 81312000 keta = 8 time = 0 keta = 9 time = 0 keta = 10 time = 0 keta = 11 time = 0 keta = 12 time = 0 keta = 13 time = 1 keta = 14 time = 2 keta = 15 time = 6 keta = 16 time = 16 keta = 17 time = 45 keta = 18 time = 127
最初の乗算(n *= 10)を外に出してみれば、もうちょいいけるかも....。 keta = 14 time = 2 keta = 15 time = 4 keta = 16 time = 12 keta = 17 time = 34 keta = 18 time = 96 微々たるもんしか減らないorz。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <stdio.h>
#include <time.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
#endif
unsigned long long int dec_base[20];
void _searchMeertens(int keta, int d, unsigned long long int r, unsigned long long int n) {
int x;
for (int x = (d == 0); x < 10; x++) {
if (x > 0) {
r *= primes[d];
if (r >= dec_base[keta])
return;
n += dec_base[keta - (d + 1)];
}
if ((d + 1) >= keta) {
if (r >= n) {
if (r == n)
printf("Found Meertens %lld\n", n);
return;
}
} else {
_searchMeertens(keta, d + 1, r, n);
}
}
}
void searchMeertens(int keta) {
int x;
time_t t;
t = time(NULL);
for (x = 1; x <= keta; x++) {
_searchMeertens(x, 0, 1, 0);
printf("keta = %d time = %d\n", x, time(NULL) - t);
t = time(NULL);
}
}
void main() {
int i;
dec_base[0] = 1;
for (i = 1; i < ARRAYSIZE(dec_base); i++) {
dec_base[i] = dec_base[i - 1] * 10;
}
searchMeertens(19);
}
|





ところてん
#4874()
[
C
]
Rating1/1=1.00
Cで書き直したら恐ろしく速くなった。 10桁実行するのに176秒@AthlonXP2500+ pythonで書いたのと比較して、だいたい100倍高速化した計算に。
ゲーテル数って10桁でintの範囲をあっさりと突破するのね・・・バグに気づかなかった。 unsigned long long int なんて初めて使ったよ。
Rating1/1=1.00-0+