- 注册时间
- 2007-12-26
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 92615
- 在线时间
- 小时
|
楼主 |
发表于 2009-8-15 22:18:13
|
显示全部楼层
这几天空闲时间我一直在琢磨这个问题,如何对自己现有的程序进行优化?如何解决空间问题?
现在终于调试好了,时间和空间的效率都非常理想:- // http://bbs.emath.ac.cn/viewthread.php?tid=1689&page=1&fromuid=8#pid21085
-
- #include <iostream>
- #include <ctime>
-
- #include <vector>
- #include <map>
- using namespace std;
-
-
- typedef unsigned int UINT32, *PUINT32;
- typedef unsigned __int64 UINT64, *PUINT64;
-
- typedef struct node
- {
- UINT32 key;
- UINT64 value;
- }NODE;
-
- typedef vector< NODE > NODE_VECTOR;
- typedef map< UINT32, UINT32 > KEY_INDEX_MAP;
- typedef KEY_INDEX_MAP::value_type MVT;
-
- #ifndef UInt32x32To64
- # define UInt32x32To64(a, b) ((UINT64)(((UINT64)(a)) * ((UINT64)(b))))
- #endif
-
- char szResult[128];
-
-
- const char * GetMin01( UINT32 n )
- {
- char * p = szResult;
-
- UINT32 i=0, j=0, d, ten, bits, index, size0, size1;
- UINT32 key;
- UINT64 value;
-
- NODE info;
- NODE_VECTOR vNode;
- KEY_INDEX_MAP mKeyIndex;
-
- KEY_INDEX_MAP::iterator it;
-
- *( p += 127 ) = '\0';
-
- // if ( 0 == n ) return p;
-
- while ( 0 == ( 1 & n ))
- {
- ++i; //times of prime 2
- n >>= 1;
- }
- while ( 0 == n % 5 )
- {
- ++j; //times of prime 5
- n /= 5;
- }
- if ( i < j ) i = j; //max times of prime 2 and prime 5
- memset( p -= i, '0', i * sizeof(char));
-
- if ( 1 == n )
- {
- *(--p) = '1';
-
- return p;
- }
-
- //special case that n+1 is 10^j
- i = n + 1;
- j = 0;
- while ( 0 == i % 10 )
- {
- ++j;
- i /= 10;
- }
- if ( 1 == i )
- {
- j *= 9;
- memset( p -= j, '1', j * sizeof(char));
-
- return p;
- }
-
- switch( n )
- {
- case 3:
- case 37: n = 111;
- break;
-
- case 7:
- case 13: n = 1001;
- break;
-
- case 337: n = 1011;
- break;
-
- case 367: n = 1101;
- break;
-
- default:
- break;
- }
-
- i = n;
- j = 0;
- while (( d = i % 10 ) <= 1 )
- {
- *(--p) = '0' + d;
- if ( 0 == ( i /= 10 ))
- {
- return p;
- }
-
- ++j;
- }
- p += j;
-
- const UINT32 INIT4BITS[] = { 0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111, };
- for ( i=0; 16!=i; ++i )
- {
- info.key = INIT4BITS[i] % n;
- info.value = i;
- vNode.push_back( info );
- mKeyIndex.insert( MVT( info.key, i ));
- }
- index = i - 1;
-
- for ( bits=4, ten=10000%n, size1=size0=vNode.size(); ; )
- {
- for ( i=1; size0!=i; ++i )
- {
- d = (UINT32)( UInt32x32To64( vNode[i].key, ten ) % n );
- if ( mKeyIndex.end() != ( it = mKeyIndex.find( n - d )))
- {
- value = vNode[(*it).second].value;
- do
- {
- *(--p) = '0' + ( 1 & value );
- value >>= 1;
- } while( 0 != --bits );
-
- value = vNode[i].value;
- do
- {
- *(--p) = '0' + ( 1 & value );
- } while( 0 != ( value >>= 1 ));
-
- return p;
- }
- }
-
- for ( i=1; size1!=i; ++i )
- {
- d = (UINT32)( UInt32x32To64( vNode[i].key, ten ) % n );
- value = vNode[i].value << bits;
-
- for ( j=0; size0!=j; ++j )
- {
- key = vNode[j].key + d;
- if ( key < d || key >= n )
- {
- key -= n;
- }
- if ( mKeyIndex.end() == mKeyIndex.find( key ))
- {
- mKeyIndex.insert( MVT( info.key = key, ++index ));
- info.value = vNode[j].value | value;
- vNode.push_back( info );
- }
- }
- }
-
- if ( size1 == size0 )
- {
- bits <<= 1;
- ten = (UINT32)( UInt32x32To64( ten, ten ) % n );
- }
- else
- {
- ++bits;
- ten = (UINT32)( UInt32x32To64( ten, 10 ) % n );
- }
-
- size0 = vNode.size();
- if ( UInt32x32To64( size0, size0 ) <= (UINT64)n )
- {
- size1 = size0;
- }
- else
- {
- size1 = 2;
- }
- }
-
- return p;
- }
-
-
- int main( void )
- {
- UINT32 n;
- const char * p;
-
- while( 1 )
- {
- cout << "N=";
- cin >> n;
-
- if( 0 == n )
- {
- break;
- }
-
- clock_t start=clock();
- p = GetMin01( n );
- clock_t end=clock();
-
- cout << p << "\n";
- cout<< "Total cost " << end-start << "ms" << "\n" << endl;
- }
-
- return 0;
- }
复制代码 其实,因今天周六,我上午就写好了代码,但测试下来有个bug,直到刚刚才debug出问题所在,郁闷死了。
而问题出在 No.161 行,之前少加了“key < d ||”(高手肯定知道它是在判定什么的吧?),
导致在输入较大的 N 时,因未判定溢出而得不到正确结果。
现在的程序效率比 mathe 的更高(当 N 非常大时),因为它无需将数据在几个 map 间进行倒腾。 |
|