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

[讨论] 数字乘积

[复制链接]
发表于 2009-3-3 17:20:38 | 显示全部楼层
mathe能否分析下
2^p * 3^q * 7^r的数字里有5或者0的概率
如果可能,能否分析出什么p, q, r组合可以满足不是一步0
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 19:05:45 | 显示全部楼层
有点担心96#程序慢了

谁给优化下
因为程序在学校跑呢
所以在家就不想重写呢

想预先Cache幂
再进行乘积的提出

应该能提高很多很多
另外,似乎用10进制更好些
呵呵
============================
看目前的结果
在支持mathe的结论
似乎12阶以上数字的没有(包括非素数)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 19:31:06 | 显示全部楼层

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <gmp.h>
  4. #include <math.h>

  5. #define l2 1700
  6. #define l3 1073
  7. #define l7 605

  8. mpz_t t3[l3 + 1], t7[l7 + 1], a, tn;
  9. char out[1024];
  10. unsigned int d[10][3];

  11. int filter(mpz_t tn)
  12. {
  13.   int e = 0, f = 0;
  14.   char * c = out;
  15.   mpz_get_str(out, 10, tn);
  16. //  printf("%s\n", out);
  17.   while (*c)
  18.   {
  19.     if (* c == '0')
  20.       return 0;
  21.     if (* c == '5') f = 1;
  22.     if ((unsigned)(*c) % 2 == 0) e = 1;
  23.     if ((f == 1) && (e == 1)) return 0;
  24.     c ++;
  25.   }
  26.   return 1;  
  27. }

  28. int main(void)
  29. {
  30.   unsigned int i, j, k;
  31.   int p = 0;

  32.   for (i = 0; i <= l3; i ++)
  33.     mpz_init(t3[i]);
  34.   
  35.   for (i = 0; i <= l7; i ++)
  36.     mpz_init(t7[i]);

  37.   mpz_set_ui(t3[0], 1);
  38.   mpz_set_ui(t7[0], 1);

  39.   for (i = 1; i <= l3; i ++)
  40.     mpz_mul_ui(t3[i], t3[i - 1], 3);
  41.   
  42.   for (i = 1; i <= l7; i ++)
  43.     mpz_mul_ui(t7[i], t7[i - 1], 7);

  44.   mpz_init(tn);
  45.   mpz_init(a);
  46.   for (j = 0; j <= l3; j ++)
  47.     for (k = 0; k <= l7; k ++)
  48.     {
  49.         mpz_mul(a, t3[j], t7[k]);
  50.         for (i = 0; i <= l2; i ++)
  51.           if (log10(2.0) * i + log10(3.0) * j + log10(7.0) * k <= 512.0)
  52.           {
  53.              mpz_mul_2exp(tn, a, i);
  54.              if (filter(tn))
  55.              {
  56.                fprintf(stdout, "%u, %u, %u\n", i, j, k);
  57.                fflush(stdout);
  58.                p ++;
  59.              }
  60.           }
  61.     }
  62.   printf("Total: %u\n", p);
  63.   mpz_clear(a);
  64.   mpz_clear(tn);
  65.   
  66.   for (i = 0; i <= l3; i ++)
  67.     mpz_clear(t3[i]);

  68.   for (i = 0; i <= l7; i ++)  
  69.     mpz_clear(t7[i]);
  70.   return 0;
  71. }
复制代码
也许这个程序速度快些
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 19:47:56 | 显示全部楼层
我可以写一个调用 HugeCalc 十进制内核的版本,但需要首先了解:

1、当前的算法或程序效率怎样?如果很快就可运行结束,就没有优化的必要了。

2、请大致讲解一些该段程序的目的,以及采用的算法原理,以便更好地优化。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 20:13:24 | 显示全部楼层
就是测试n = 2^p * 3^q * 7^r
n 小于一个给定数字比如10^512
如果n的十进制表示中包含0或者同时有5和某个偶数则抛弃n
否则,输出p, q, r
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 20:14:34 | 显示全部楼层
102# 还可以再优化的

看512位内的结果情况
如果没有结果
也许优化了继续算到1000位

呵呵
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 20:15:50 | 显示全部楼层
候选者有上亿个呢
所以不可能很快就完成

96#是个很慢的程序
正在学校运行

怀疑明天到学校去的时候也完成不了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 20:51:46 | 显示全部楼层

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <gmp.h>
  4. #include <math.h>

  5. #define l2 1700
  6. #define l3 1073
  7. #define l7 605

  8. mpz_t a, b, tn;
  9. char out[1024];
  10. unsigned int d[10][3];

  11. int filter(mpz_t tn)
  12. {
  13.   int e = 0, f = 0;
  14.   char * c = out;
  15.   mpz_get_str(out, 10, tn);
  16. //  printf("%s\n", out);
  17.   while (*c)
  18.   {
  19.     if (* c == '0')
  20.       return 0;
  21.     if (* c == '5') f = 1;
  22.     if ((unsigned)(*c) % 2 == 0) e = 1;
  23.     if ((f == 1) && (e == 1)) return 0;
  24.     c ++;
  25.   }
  26.   return 1;  
  27. }

  28. int main(void)
  29. {
  30.   unsigned int i, j, k;
  31.   int p = 0;

  32.   mpz_init(tn);
  33.   mpz_init(a);
  34.   mpz_init(b);
  35.   mpz_set_ui(a, 1);
  36.   mpz_set_ui(b, 1);
  37.   for (j = 0; j <= l3; j ++)
  38.   {
  39.     for (k = 0; k <= l7; k ++)
  40.     {
  41.         for (i = 0; i <= l2, log10(2.0) * i + log10(3.0) * j + log10(7.0) * k <= 512.0; i ++)
  42.           {
  43.              if (filter(tn))
  44.              {
  45.                fprintf(stdout, "%u, %u, %u\n", i, j, k);
  46.                fflush(stdout);
  47.                p ++;
  48.              }
  49.              mpz_mul_ui(tn, tn, 2);
  50.           }
  51.         mpz_mul_ui(b, b, 7);
  52.         mpz_set(tn, b);
  53.     }
  54.     mpz_mul_ui(a, a, 3);
  55.     mpz_set(b, a);
  56.   }
  57.   printf("Total: %u\n", p);
  58.   mpz_clear(a);
  59.   mpz_clear(b);
  60.   mpz_clear(tn);
  61.   
  62.   return 0;
  63. }
复制代码
简化了下
不知道是否更好
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 21:24:00 | 显示全部楼层

优化 102# 无心人 的程序

  1. #include <stdio.h>

  2. #include "../../../HugeCalc_API/CppAPI/Include/HugeCalc.h"  // 公共接口
  3. #include "../../../HugeCalc_API/CppAPI/Include/HugeInt.h"   // 10进制系统

  4. #pragma message( "automatic link to ../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
  5. #pragma comment( lib, "../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )

  6. #define DIGIT_MAX   128

  7. BOOL filter( const CHugeInt& hugeNum )
  8. {
  9.     LPCTSTR p = (LPCTSTR)hugeNum;
  10.     BOOL b2 = FALSE;

  11.     do
  12.     {
  13.         if ( 0 == (((UINT32)*p) & 1) )
  14.         {
  15.             if ( '0' == *p )
  16.             {
  17.                 return FALSE;
  18.             }

  19.             b2 = TRUE;
  20.             break;
  21.         }
  22.         else if ( '5' == *p )
  23.         {
  24.             break;
  25.         }
  26.     } while( NULL != *(++p) );

  27.     if ( NULL != *p )
  28.     {
  29.         if ( b2 )
  30.         {
  31.             while ( NULL != *(++p) )
  32.             {
  33.                 if ( '0' == *p || '5' == *p )
  34.                 {
  35.                     return FALSE;
  36.                 }
  37.             }
  38.         }
  39.         else
  40.         {
  41.             while ( NULL != *(++p) )
  42.             {
  43.                 if ( 0 == (((UINT32)*p) & 1) )
  44.                 {
  45.                     return FALSE;
  46.                 }
  47.             }
  48.         }
  49.     }

  50.     return TRUE;
  51. }

  52. int main(int argc, char* argv[])
  53. {
  54.     UINT32 exp7, exp3, exp2, count = 0;
  55.     CHugeInt huge7, huge73, huge732;

  56.     printf( "Call %s\n", HugeCalc::GetVer());
  57.     if ( HC_LICENSE_NONE == HugeCalc::GetLicenseLevel())
  58.     {
  59.         printf( "\n警告:您未通过 HugeCalc.dll 的许可认证!\n" \
  60.                 "\n解决方案可选下列方案之一:" \
  61.                 "\n    一、请将本程序移动到“/CopyrightByGuoXianqiang/[../]”目录下运行;" \
  62.                 "\n    二、或请在 HugeCalc.chm 中进行注册(一劳永逸)。\n\n" );

  63.         system( "pause" );
  64.         return (-1);
  65.     }

  66.     HugeCalc::EnableTimer( TRUE );
  67.     HugeCalc::ResetTimer();

  68.     exp7 = 0;
  69.     huge7 = 1;
  70.     do
  71.     {
  72.         exp3 = 0;
  73.         huge73 = huge7;
  74.         do
  75.         {
  76.             exp2 = 0;
  77.             huge732 = huge73;
  78.             do
  79.             {

  80.                 if ( filter( huge732 ) )
  81.                 {
  82.                     fprintf(stdout, "%s  No.%u\texp( 2, 3, 7 ) = ( %u, %u, %u )\n",
  83.                         HugeCalc::GetTimerStr( FT_HHMMSS_ms ), ++count, exp2, exp3, exp7 );
  84.                     fflush(stdout);
  85.                 }

  86.             } while( ++exp2, ( huge732 *= 2 ).GetDigits() <= DIGIT_MAX );

  87.         } while( ++exp3, ( huge73 *= 3 ).GetDigits() <= DIGIT_MAX );

  88.     } while( ++exp7, ( huge7 *= 7 ).GetDigits() <= DIGIT_MAX );

  89.     printf( "\n****** %s ******\n", HugeCalc::GetTimerStr( FT_DOT06SEC_s ) );
  90.     system( "pause" );

  91.     return 0;
  92. }
复制代码
上述代码经过了一些优化,效率非常高。
若将宏 DIGIT_MAX 定义成 128,则 2.371397 s 内就可得到全部 1105 组解:
  1. . . .
  2. 00:00:00.985  No.1084   exp( 2, 3, 7 ) = ( 7, 4, 20 )
  3. 00:00:00.986  No.1085   exp( 2, 3, 7 ) = ( 43, 10, 20 )
  4. 00:00:00.988  No.1086   exp( 2, 3, 7 ) = ( 51, 21, 20 )
  5. 00:00:01.014  No.1087   exp( 2, 3, 7 ) = ( 5, 11, 21 )
  6. 00:00:01.017  No.1088   exp( 2, 3, 7 ) = ( 16, 27, 21 )
  7. 00:00:01.040  No.1089   exp( 2, 3, 7 ) = ( 12, 2, 22 )
  8. 00:00:01.042  No.1090   exp( 2, 3, 7 ) = ( 36, 4, 22 )
  9. 00:00:01.042  No.1091   exp( 2, 3, 7 ) = ( 20, 5, 22 )
  10. 00:00:01.047  No.1092   exp( 2, 3, 7 ) = ( 9, 31, 22 )
  11. 00:00:01.068  No.1093   exp( 2, 3, 7 ) = ( 15, 0, 23 )
  12. 00:00:01.069  No.1094   exp( 2, 3, 7 ) = ( 4, 1, 23 )
  13. 00:00:01.069  No.1095   exp( 2, 3, 7 ) = ( 5, 1, 23 )
  14. 00:00:01.069  No.1096   exp( 2, 3, 7 ) = ( 8, 3, 23 )
  15. 00:00:01.070  No.1097   exp( 2, 3, 7 ) = ( 7, 8, 23 )
  16. 00:00:01.070  No.1098   exp( 2, 3, 7 ) = ( 21, 9, 23 )
  17. 00:00:01.123  No.1099   exp( 2, 3, 7 ) = ( 5, 2, 25 )
  18. 00:00:01.151  No.1100   exp( 2, 3, 7 ) = ( 5, 6, 26 )
  19. 00:00:01.185  No.1101   exp( 2, 3, 7 ) = ( 1, 23, 27 )
  20. 00:00:01.258  No.1102   exp( 2, 3, 7 ) = ( 26, 10, 30 )
  21. 00:00:01.448  No.1103   exp( 2, 3, 7 ) = ( 19, 0, 38 )
  22. 00:00:01.452  No.1104   exp( 2, 3, 7 ) = ( 4, 17, 38 )
  23. 00:00:01.557  No.1105   exp( 2, 3, 7 ) = ( 14, 4, 43 )

  24. ****** 2.371397 s ******
  25. 请按任意键继续. . .
复制代码

D128.txt

56.18 KB, 下载次数: 1, 下载积分: 金币 -1 枚, 经验 1 点, 下载 1 次

运行结果

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-3 21:35:45 | 显示全部楼层
确实很快

GMP的二进制内核的输出太慢了
导致过滤函数成为瓶颈
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-5-18 22:51 , Processed in 0.046707 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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