找回密码
 欢迎注册
楼主: northwolves

[擂台] Ten digit numbers

[复制链接]
发表于 9 小时前 | 显示全部楼层
上面的公式有个问题,没有考虑到对于越大的数,对应的计算量越大。由于我们实际计算过程都是一个超大整数乘上一个小于\(10^{10}\)的整数
所以实际上每次乘法本身就是O(n)的,由此总体复杂度可以表示为
\(\sum_{x=10^9}^{10^{10}-1}\frac{x\ln(0.1)}{\ln(10^{-10}x)}\approx 10^{20}\ln(0.1)(Ei(2\ln(1-10^{-10}))-Ei(2\ln(0.1)))\).
而计算过程中,如果我们从\(10^9\)已经计算到\(10^{10}-10^7\),那么我们就可以估算出计算过程已经占了整体计算量的
\(\frac{Ei(2\ln(0.999))-Ei(2\ln(0.1)))}{Ei(2\ln(1-10^{-10}))-Ei(2\ln(0.1)))} \approx 0.2088\)
通过这种方法可以估算出完成整个计算大概需要8K CPU日左右, 对于现代多核处理器也不是不能完成,就是时间略微长了点,如果能够优化一下会更好。
  1. #include <math.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <time.h>

  5. #define SN 501
  6. #define MP 100000000

  7. #define MOD 10000000000L
  8. #define HMOD 100000

  9. char dc[HMOD][10];
  10. void initdc()
  11. {
  12.   int i;
  13.   for(i=0;i<HMOD;i++){
  14.     int j;
  15.     int x=i;
  16.     for(j=0;j<5;j++){
  17.       dc[i][x%10]++;
  18.       x/=10;
  19.     }
  20.   }
  21. }

  22. void get_count(long v[],int length, int count[10])
  23. {
  24.   int i;
  25.   for(i=0;i<10;i++)count[i]=0;
  26.   for(i=0;i<length;i++){
  27.     int x=v[i]%HMOD;
  28.     int y=v[i]/HMOD;
  29.     int j;
  30.     for(j=0;j<10;j++){
  31.       count[j]+=dc[x][j]+dc[y][j];
  32.     }
  33.   }
  34. }

  35. bool mulby(long v[], int length, long m)
  36. {
  37.   int i;
  38.   long carry=0L;
  39.   for(i=0;i<length;i++){
  40.     __int128_t prod = (__int128_t)v[i]*m+carry;
  41.     v[i]=prod%MOD;
  42.     carry=prod/MOD;
  43.   }
  44.   v[length]=carry;
  45.   return carry>=(MOD/10);
  46. }

  47. int main()
  48. {
  49.     double sv=pow(0.1,1.0/SN)*MOD;
  50.     long is = (long)ceil(sv);
  51.     initdc();
  52.     time_t start=time(NULL);
  53. #pragma omp parallel
  54.     {
  55.       long *data = (long *)malloc((MP+1)*sizeof(long));
  56. #pragma omp for schedule(dynamic)
  57.     for(long i=is;i<MOD;i++){
  58.             int count[10];
  59.       data[0]=i;
  60.         int j;
  61.         for(j=2;j<=MP;j++){
  62.     if(!mulby(data,j-1,i))break;
  63.     if(j<SN)continue;
  64.     get_count(data,j,count);
  65.             int k;
  66.             for(k=0;k<10;k++)if(count[k]!=j)break;
  67.             if(k==10){
  68. #pragma omp critical
  69.                     {
  70.                         printf("%ld^%d\n",i,j);
  71.                               fflush(stdout);
  72.                     }
  73.             }
  74.         }
  75. #pragma omp critical
  76.         if(i%1000000==0)
  77.         {
  78.                 time_t now=time(NULL);
  79.                 fprintf(stderr,"%ld cost %ld\n",i,now-start);
  80.                 fflush(stderr);
  81.         }
  82.     }
  83.     }
  84.     printf("done!\n");
  85.     return 0;
  86. }
复制代码

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2025-11-5 17:16 , Processed in 0.024513 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表