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

[擂台] 求由0和1构成的最小十进制正整数,其是指定正整数的倍数

[复制链接]
 楼主| 发表于 2009-8-17 15:26:25 | 显示全部楼层
可否针对 $10^k-1$ 整数倍的数采用特殊的加速算法?

$N=(10^k-1)/3$, $M=(10^(3k)-1)/9$

$N=(10^k-1)$, $M=(10^(9k)-1)/9$

$N=3(10^k-1)$, $M=(10^(9k+1)-1)/9 - 10^(7k)$

$N=9(10^k-1)$, $M=(10^(9k+1)-1)/9 - 10^k$
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-8-17 16:54:04 | 显示全部楼层
应该可以,但是不排除还存在其它超过64比特的值
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-8-18 08:44:57 | 显示全部楼层

最终版本

综合 31# 发现的规律,以及 32# 的忠告,
将代码最终修订如下:
  1. //  http://bbs.emath.ac.cn/viewthread.php?tid=1689&page=4&fromuid=8#pid21134

  2. #include <iostream>
  3. #include <ctime>

  4. #include <vector>
  5. #include <map>
  6. #include <algorithm>
  7. using namespace std;


  8. typedef unsigned int UINT32, *PUINT32;
  9. typedef unsigned __int64 UINT64, *PUINT64;

  10. typedef vector< UINT32 >            U32_VECTOR;
  11. typedef vector< UINT64 >            U64_VECTOR;
  12. typedef map< UINT32, UINT32 >       KEY_INDEX_MAP;
  13. typedef KEY_INDEX_MAP::value_type   MVT;

  14. #ifndef UInt32x32To64
  15. #     define UInt32x32To64(a, b)    ((UINT64)(((UINT64)(a)) * ((UINT64)(b))))
  16. #endif

  17. #define FAST_SIZE                    36

  18. const UINT32 FAST_N[FAST_SIZE] = { 3, 9, 27, 33, 81, 99, 297, 333, 891, 999, 2997, 3333, 8991, 9999, 29997, 33333, 89991, 99999, 299997, 333333, 899991, 999999, 2999997, 3333333, 8999991, 9999999, 29999997, 33333333, 89999991, 99999999, 299999997, 333333333, 899999991, 999999999, 2999999997, 3333333333 };
  19. const UINT32 FAST_M[FAST_SIZE] = { 3, 9, (7<<16)|10, 6, (1<<16)|10, 18, (14<<16)|19, 9, (2<<16)|19, 27, (21<<16)|28, 12, (3<<16)|28, 36, (28<<16)|37, 15, (4<<16)|37, 45, (35<<16)|46, 18, (5<<16)|46, 54, (42<<16)|55, 21, (6<<16)|55, 63, (49<<16)|64, 24, (7<<16)|64, 72, (56<<16)|73, 27, (8<<16)|73, 81, (63<<16)|82, 30 };

  20. char szResult[128];


  21. __declspec(naked)
  22. UINT32 DivMod5( UINT32& n )
  23. {
  24.     __asm
  25.     {
  26.         mov     ecx, dword ptr[esp + 0x04];

  27.         mov     edx, dword ptr[ecx];
  28.         mov     eax, 0xCCCCCCCD;
  29.         push    edx;

  30.         mul     edx;
  31.         shr     edx, 2;
  32.         mov     dword ptr[ecx], edx;

  33.         lea     edx, [edx + 0x04*edx];

  34.         pop     eax;
  35.         sub     eax, edx;

  36.         ret;
  37.     }
  38. }


  39. __declspec(naked)
  40. UINT32 DivMod10( UINT32& n )
  41. {
  42.     __asm
  43.     {
  44.         mov     ecx, dword ptr[esp + 0x04];

  45.         mov     edx, dword ptr[ecx];
  46.         mov     eax, 0xCCCCCCCD;
  47.         push    edx;

  48.         mul     edx;
  49.         shr     edx, 3;
  50.         mov     dword ptr[ecx], edx;

  51.         imul    edx, 10;

  52.         pop     eax;
  53.         sub     eax, edx;

  54.         ret;
  55.     }
  56. }


  57. const char * GetMin01( UINT32 n )
  58. {
  59.     char * p = szResult;

  60.     UINT32 i=0, j=0, d, ten, bits, index, size0, size1;
  61.     UINT32 key;
  62.     UINT64 value;

  63.     U32_VECTOR vKey;
  64.     U64_VECTOR vValue;
  65.     KEY_INDEX_MAP mKeyIndex;

  66.     KEY_INDEX_MAP::iterator it;

  67.     *( p += 127 ) = '\0';

  68. //  if ( 0 == n ) return p;

  69.     while ( 0 == ( 1 & n ))
  70.     {
  71.         ++i;    //times of prime 2
  72.         n >>= 1;
  73.     }

  74.     while ( 0 == ( d = DivMod5( n )))
  75.     {
  76.         ++j;    //times of prime 5
  77.     }
  78.     n = n * 5 + d;

  79.     if ( i < j ) i = j; //max times of prime 2 and prime 5
  80.     memset( p -= i, '0', i * sizeof(char));

  81.     i = n;
  82.     j = 0;
  83.     while (( d = DivMod10( i )) <= 1 )
  84.     {
  85.         ++j;

  86.         *(--p) = '0' + d;
  87.         if ( 0 == i )
  88.         {
  89.             return p;
  90.         }
  91.     }
  92.     p += j;

  93.     //special case
  94.     const UINT32 * pFast = lower_bound( FAST_N, FAST_N + FAST_SIZE, n );
  95.     if ( FAST_N + FAST_SIZE != pFast && n == *pFast )
  96.     {
  97.         d = FAST_M[ pFast - FAST_N ];
  98.         i = d & 0xFFFF;
  99.         j = d >> 16;

  100.         memset( p -= i, '1', i * sizeof(char));
  101.         if ( 0 != j )
  102.         {
  103.             *( p + i - j - 1 ) = '0';
  104.         }

  105.         return p;
  106.     }

  107.     vKey.push_back( 0 );
  108.     vValue.push_back( 0 );
  109.     mKeyIndex.insert( MVT( 0, index = 0 ));

  110.     vKey.push_back( 1 );
  111.     vValue.push_back( 1 );
  112.     mKeyIndex.insert( MVT( 1, ++index ));

  113.     for ( bits=1, ten=10%n, size1=size0=vKey.size(); ; )
  114.     {
  115.         for ( i=1; size0!=i; ++i )
  116.         {
  117.             d = (UINT32)( UInt32x32To64( vKey[i], ten ) % n );
  118.             if ( mKeyIndex.end() != ( it = mKeyIndex.find( n - d )))
  119.             {
  120.                 value = vValue[(*it).second];
  121.                 do
  122.                 {
  123.                     *(--p) = '0' + ( 1 & value );
  124.                     value >>= 1;
  125.                 } while( 0 != --bits );

  126.                 value = vValue[i];
  127.                 do
  128.                 {
  129.                     *(--p) = '0' + ( 1 & value );
  130.                 } while( 0 != ( value >>= 1 ));

  131.                 return p;
  132.             }
  133.         }

  134.         for ( i=1; size1!=i; ++i )
  135.         {
  136.             d = (UINT32)( UInt32x32To64( vKey[i], ten ) % n );
  137.             value = vValue[i] << bits;

  138.             for ( j=0; size0!=j; ++j )
  139.             {
  140.                 if ( key = vKey[j] + d, key < d || key >= n )
  141.                 {
  142.                     key -= n;
  143.                 }
  144.                 if ( mKeyIndex.end() == mKeyIndex.find( key ))
  145.                 {
  146.                     vKey.push_back( key );
  147.                     vValue.push_back( vValue[j] | value );
  148.                     mKeyIndex.insert( MVT( key, ++index ));
  149.                 }
  150.             }
  151.         }

  152.         if ( size1 == size0 )
  153.         {
  154.             bits <<= 1;
  155.             ten = (UINT32)( UInt32x32To64( ten, ten ) % n );
  156.         }
  157.         else
  158.         {
  159.             ++bits;
  160.             ten = (UINT32)( UInt32x32To64( ten, 10 ) % n );
  161.         }

  162.         size0 = vKey.size();
  163.         size1 = ( bits < 16 ) ? size0 : 2;
  164.     }

  165.     return p;
  166. }


  167. int main( void )
  168. {
  169.     UINT32 n;
  170.     const char * p;

  171.     while( 1 )
  172.     {
  173.         cout << "N=";
  174.         cin >> n;

  175.         if( 0 == n )
  176.         {
  177.             break;
  178.         }

  179.         clock_t start=clock();
  180.         p = GetMin01( n );
  181.         clock_t end=clock();

  182.         cout << p << "\n";
  183.         cout<< "Total cost " << end-start << "ms" << "\n" << endl;
  184.     }

  185.     return 0;
  186. }
复制代码
(由于效率已比较高了,且排除了bug的可能,所以上述代码我将不再会去修改了。)

在 VC6.0 环境下编译得到: search_pid21134.zip (24.4 KB, 下载次数: 12)

运行示例:
N=699999993
111111111111111111111111111111111111111111111111111111111111111111111111
Total cost 19906ms

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

本版积分规则

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

GMT+8, 2024-4-20 12:00 , Processed in 0.044307 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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