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

[讨论] 猜猜我的手机号码?

[复制链接]
发表于 2009-8-25 11:34:42 | 显示全部楼层
如果在已知:前三位为189,末两位为43,11个数字分别为:01123456789,且为两个素数之积,其中一素数为5位数。
则存在一些快速算法,比如说:

1、根据末两位为43,且为两素数之积,可先建立100内正奇数的乘法表,筛选出积末两位为43者的组合;

2、可先建立素数表,范围为:10000~1899999;

3、试算时,在确定一素数后,可以马上确定出另一素数的取值范围;

4、在计算出两素数乘积(需64位存储)后,可以马上减去18900000043,这样仅保留中间的6位数字,可以用DWORD类型数据存储;

5、在统计数字字符时,需要将数字转化为10进制字符,此处有些快速算法,可完全避免除法指令进行提速;或将012567六个数字全排列后排序,而后进行二分查找判定。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 13:01:08 | 显示全部楼层
31# gxqcn

请提供一个代码吧
我的代码已经用到了你的若干建议
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 13:04:35 | 显示全部楼层
具体代码我不想写了,结果应该在秒级内输出。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 15:55:41 | 显示全部楼层
具体代码我不想写了,结果应该在秒级内输出。
gxqcn 发表于 2009-8-25 13:04

我用30楼代码 if( temp>189e8 &&  temp<190e8 )还是9秒,不知道什么时候限制1出现2次
medie2005 的最大时间耗费是什么,int64的mod /运算?
你的建议中最大缩短时间是靠什么?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 16:56:05 | 显示全部楼层
下面的代码,用了 STL,还调用了 HugeCalc 以快速生成素数表及统计耗时:
  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;

  4. #include "../../../HugeCalc_API/CppAPI/Include/HugeCalc.h"    // 公共接口

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


  7. int main(int argc, char* argv[])
  8. {
  9. //    printf("Hello World!\n");

  10.     cout << "Call " << HugeCalc::GetVer() << endl << endl;

  11.     // 初始化
  12.     HugeCalc::EnableTimer( TRUE );
  13.     HugeCalc::ResetTimer();

  14.     UINT32 i, j;
  15.     UINT32 u32Size = HugeCalc::GetPrimeCount( 10000, 1899999 );
  16.     UINT32 * pPrimeBuffer = new UINT32[u32Size];
  17.     HugeCalc::GetPrimeList( pPrimeBuffer, u32Size, 10000, 1899999 );

  18.     UINT32 LUT[720], u32Dights[6] = { 0, 1, 2, 5, 6, 7 };
  19.     UINT32 *p, *p1, *p2, *p_end;

  20.     *( p = LUT ) = 1256743; /* 012567 43 */
  21.     while( next_permutation( u32Dights, u32Dights+6 ))
  22.     {
  23.         for ( i=0, j=0; 6!=j; ++j )
  24.         {
  25.             i = i * 10 + u32Dights[j];
  26.         }
  27.         *(++p) = i * 100 + 43;
  28.     }

  29.     p1 = pPrimeBuffer;
  30.     do
  31.     {
  32.         p2 = lower_bound( p1, pPrimeBuffer + u32Size, (UINT32)((UINT64)18901256743 / *p1 ));
  33.         p_end = lower_bound( p2, pPrimeBuffer + u32Size, (UINT32)((UINT64)18976521043 / *p1 )+1 );

  34.         do
  35.         {
  36.             i = (UINT32)( UInt32x32To64( *p1, *p2 ) - (UINT64)18900000000 );
  37.             p = lower_bound( LUT, LUT+720, i );

  38.             if ( LUT+720 != p && i == *p )
  39.             {
  40.                 cout << ((*p>=10000000)?"189":"1890") << *p << " = " << *p1 << " * " << *p2 << endl;
  41.             }
  42.         }while( p_end != ++p2 );

  43.     } while( *(++p1) <= 99999 );

  44.     delete []pPrimeBuffer;

  45.     HugeCalc::EnableTimer( FALSE );

  46.     cout << endl << "耗时为:" << HugeCalc::GetTimerStr( FT_DOT06SEC_s ) << endl;

  47.     return 0;
  48. }
复制代码
请将上述代码复制粘贴进 [..]\CopyrightByGuoXianqiang\HugeCalc\testDLL\src\ANSI_C++\ansi_c++.cpp,然后编译运行即可。

它运行速度非常快,结果如下:
  1. Call HugeCalc V8.1.0.0 (Win32)

  2. 18962715043 = 11173 * 1697191
  3. 18960217543 = 13037 * 1454339
  4. 18927156043 = 13187 * 1435289
  5. 18952607143 = 13291 * 1425973
  6. 18967512043 = 13799 * 1374557
  7. 18926501743 = 13841 * 1367423
  8. 18957201643 = 15077 * 1257359
  9. 18962107543 = 16223 * 1168841
  10. 18965210743 = 16631 * 1140353
  11. 18950726143 = 17123 * 1106741
  12. 18907561243 = 20357 * 928799
  13. 18965710243 = 21023 * 902141
  14. 18917062543 = 21817 * 867079
  15. 18927615043 = 21893 * 864551
  16. 18967102543 = 22247 * 852569
  17. 18920516743 = 25183 * 751321
  18. 18901652743 = 26501 * 713243
  19. 18910725643 = 28657 * 659899
  20. 18927610543 = 28807 * 657049
  21. 18912076543 = 29269 * 646147
  22. 18910765243 = 29569 * 639547
  23. 18912576043 = 33773 * 559991
  24. 18927160543 = 34351 * 550993
  25. 18961270543 = 34367 * 551729
  26. 18976105243 = 36527 * 519509
  27. 18965172043 = 37309 * 508327
  28. 18925160743 = 41981 * 450803
  29. 18910625743 = 42131 * 448853
  30. 18927016543 = 46171 * 409933
  31. 18921567043 = 46867 * 403729
  32. 18927561043 = 49463 * 382661
  33. 18951207643 = 52201 * 363043
  34. 18902756143 = 56893 * 332251
  35. 18970162543 = 66509 * 285227
  36. 18921675043 = 66571 * 284233
  37. 18917065243 = 70957 * 266599
  38. 18950126743 = 76603 * 247381
  39. 18925671043 = 83101 * 227743
  40. 18907652143 = 87049 * 217207
  41. 18916705243 = 95891 * 197273
  42. 18957062143 = 99023 * 191441

  43. 耗时为:0.174513 s
  44. Press any key to continue
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 17:17:10 | 显示全部楼层
对于gxqcn的这个问题,总共才6!=720个候选数,我觉得直接因子分解它们可能会更加快
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 18:18:34 | 显示全部楼层
分解用费马法即可.
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 18:20:01 | 显示全部楼层
其实这里试除也就可以了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 18:23:26 | 显示全部楼层
用LiDIA写了个程序,不过发现速度不快6秒.这个应该是使用通用的因子分解算法的问题:

  1. #include "LiDIA/bigint.h"
  2. #include "LiDIA/rational_factorization.h"
  3. #include <algorithm>
  4. using namespace std;
  5. using namespace LiDIA;

  6. static int digitss[6]={0,1,2,5,6,7};

  7. int main()
  8. {
  9.         int i,j;
  10.         long long r;
  11.         bigint v=1890;
  12.         v*=10000000;
  13.         do{
  14.                 for(i=0,j=0;j!=6;j++){
  15.                         i=i*10+digitss[j];
  16.                 }
  17.                 i=i*100+43;
  18.                 bigint b=v+i;
  19.                 rational_factorization fr(b);
  20.                 fr.factor(3);
  21.                 if(fr.no_of_comp()==2){
  22.                         for(j=0;j<2;j++){
  23.                                 if(fr.exponent(j)!=1)
  24.                                         break;
  25.                         }
  26.                         if(j==2){
  27.                                 bigint v1=fr.base(0);
  28.                                 bigint v2=fr.base(1);
  29.                                 if(v1>=10000&&v1<=10000000&&v2>=10000&&v2<=10000000){
  30.                                         int u1,u2;
  31.                                         v1.intify(u1);v2.intify(u2);
  32.                                         printf("189%08d=%d*%d\n",i,u1,u2);
  33.                                 }
  34.                         }
  35.                 }
  36.         }while(next_permutation(digitss,digitss+6));
  37. }
复制代码
不过结果有46个,同gxqcn不完全相同
18901652743=26501*713243
18902756143=56893*332251
18907561243=20357*928799
18907652143=87049*217207
18910625743=42131*448853
18910725643=28657*659899
18910765243=29569*639547
18912065743=111521*169583
18912076543=29269*646147
18912576043=33773*559991
18916705243=95891*197273
18917062543=21817*867079
18917065243=70957*266599
18920516743=25183*751321
18920716543=108947*173669
18921567043=46867*403729
18921675043=66571*284233
18925160743=41981*450803
18925671043=83101*227743
18926501743=13841*1367423
18927016543=46171*409933
18927156043=13187*1435289
18927160543=34351*550993
18927561043=49463*382661
18927610543=28807*657049
18927615043=21893*864551
18950126743=76603*247381
18950621743=121139*156437
18950726143=17123*1106741
18951207643=52201*363043
18952607143=13291*1425973
18957062143=99023*191441
18957201643=15077*1257359
18960217543=13037*1454339
18961027543=109507*173149
18961270543=34367*551729
18962107543=16223*1168841
18962715043=11173*1697191
18965172043=37309*508327
18965210743=16631*1140353
18965710243=21023*902141
18967102543=22247*852569
18967512043=13799*1374557
18970162543=66509*285227
18972506143=112501*168643
18976105243=36527*519509
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-25 18:45:58 | 显示全部楼层
我的结果与 22# medie2005 的一致。
mathe 漏了一个限定条件:其中一个素因子为5位数。

虽然候选数不多,但试乘法比因子分解法效率高得多,所以我一开始就偏向于用试算法。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-4-19 11:16 , Processed in 0.043229 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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