#include <stdio.h> #include <stdlib.h> typedef unsigned long long U64; typedef unsigned short gtype; gtype gmax = 1; U64 kmax = 1; #define LEAP_BITS 10 #define LEAP_N (1<<LEAP_BITS) #define LMASK (LEAP_N-1) U64 atab[LEAP_N], btab[LEAP_N]; U64 thtab[LEAP_N]; gtype gtab[LEAP_N]; #define SKIP_BITS 16 #define SKIP_MASK ((1<<SKIP_BITS)-1) char skip_tab[1<<SKIP_BITS]; #define GTABLE_MAX ((1<<20)*32) gtype gtable[GTABLE_MAX]; #define LOONG_MASK ((1LL<<48)-1) #define LOONG_BITS 48 /* 64 48 32 16 01 *XH ****************** * 64 48 32 16 01 *XL MARGIN************ */ // b < 1^16 is assumed #define LOONG_ADD(xh,xl,b) {xl+=b;xh += xl>>LOONG_BITS;xl&=LOONG_MASK;} #define LOONG_MUL(xh,xl,b) {xl*=b;xh = xh*b + (xl>>LOONG_BITS);xl&=LOONG_MASK;} void handle_loong(U64 *x, gtype *g) { int g0 = 0; U64 xh, xl; U64 x64 = *x; xl = x64&LOONG_MASK; xh = x64 >>LOONG_BITS; while ( xh != 0) { int c = xl & LMASK; U64 a = atab[c]; U64 b = btab[c]; xl >>=LEAP_BITS; xl |= (xh&LMASK) << (LOONG_BITS-LEAP_BITS); xh >>= LEAP_BITS; LOONG_MUL(xh, xl, a); LOONG_ADD(xh, xl, b); g0 += gtab[c]; } *x = xl; (*g) += g0; } void do_check(U64 k) { int i; #define H_BUFSIZE (1<<16) U64 x_log[H_BUFSIZE]; gtype g_log[H_BUFSIZE]; gtype g=0; int n_log = 0; U64 x = k; while(1) { if (x <= GTABLE_MAX) { if (gtable[x-1] != 0) break; x_log[n_log] = x; g_log[n_log] = g; n_log++; if (x & 1) x = x*3+1; else x >>=1; g++; } else { //Hot Spot U64 m = x>>LEAP_BITS; int c = x & LMASK; if (m >= thtab[c]) handle_loong(&x, &g); else { x = m*atab[c]+btab[c]; g += gtab[c]; } } } g += gtable[x-1]; for(i=0;i<n_log;i++) { gtable[x_log[i]-1] = g-g_log[i]; } if (g>=gmax) { gmax = g; kmax = k; printf("g(%lld)=%d\n",kmax,gmax); } } int main(int argc, char **argv) { //U64 n = atoll(argv[1]); U64 n = 1LL<<atoll(argv[1]); U64 k, i, n0; gtable[0] = 1; for(i=1;i<GTABLE_MAX;i++) gtable[i] = 0; init_leap_table(LEAP_BITS, atab,btab,gtab,thtab); init_skip_tab(SKIP_BITS, skip_tab); n0=n/2; n0 >>=SKIP_BITS; n0/=6; n0*=6; n0 <<=SKIP_BITS; for(k=n0;k<=n;) { if(skip_tab[k&SKIP_MASK])do_check(k);k++; //0 if(skip_tab[k&SKIP_MASK])do_check(k);k+=2; //1 if(skip_tab[k&SKIP_MASK])do_check(k);k+=3; //3 if(k%(n/600)==0)printf("%lld/%lld\n",k,n); } printf("g(%lld)=%d\n",kmax,gmax); }