网友Mutalisk给的一道题目,
计算 (1+2^0)*(1+2^1)*(1+2^2)…(1+2^32)
今晚赶回家了,花了几十分钟写好了代码,计算结果和Mutalisk的一样。运行时间为10毫秒,当然,是在我PIII 900Mhz的机子上,基本上一闪就出结果。
我的结果是160位,
41900194778866063098
69616409977680717118
75372548418310142014
25167533420258842344
35351687855236795051
88646940175563375578
68147135401121187966
16074978167792968750
内容:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct big_number{
int d[64]; // 4*64 256λ
int len;
}exp2[40], ans;
void print( big_number & b )
{
int i, j;
for( i=b.len-1; i>=0; i-- ){
for( j=1000; j>=1; j/=10 )
if( !(i==b.len-1 && j>1 && b.d[i]<j ) )
printf("%d", (b.d[i]/j)%10 );
}
}
void mul( big_number & b, int a )
{
int i, r;
r = 0;
for( i=0; i<b.len; i++ ){
r = r + b.d[i] * a;
b.d[i] = r % 10000;
r /= 10000;
}
//ÏÂÃæÑ»·¿ÉÒÔÓÅ»¯
while( r>0 ){
b.d[b.len++] = r % 10000;
r /= 10000;
}
}
void mul2( big_number &a, big_number &b )
{
int i, j, k, p, r;
big_number c; //result
memset( &c, 0, sizeof(c) );
for( i=0; i<b.len; i++ ){
p = b.d[i];
for( k=0, j=i, r=0; k<a.len; k++, j++ ){
r = r + a.d[k] * p + c.d[j];
c.d[j] = r % 10000;
r /= 10000;
}
//ÏÂÃæÑ»·¿ÉÒÔÓÅ»¯È¥µô
while( r>0 ){
r = c.d[j] + r;
c.d[j] = r % 10000;
r /= 10000;
j ++;
}
c.len = j;
}
a = c;
}
void add( big_number & a, big_number & b )
{
int i, r;
r = 0;
a.len = a.len<b.len ? b.len : a.len;
for( i=0; i<a.len; i++ ){
r = r + a.d[i] + b.d[i];
a.d[i] = r % 10000;
r /= 10000;
}
//ÏÂÃæÒ»²œ¿ÉÒÔÓÅ»¯
while( r>0 ){
a.d[a.len++] = r % 10000;
r /= 10000;
}
}
int is_bigger( big_number & a, big_number & b )
{
if( a.len > b.len )
return 1;
else if( a.len < b.len )
return 0;
int i;
for( i=a.len-1; i>=0; i-- ){
if( a.d[i] > b.d[i] )
return 1;
else if( a.d[i] < b.d[i] )
return 0;
}
return 0;
}
//ŒÆËã2µÄ·œ
void prepare()
{
int i,j;
memset( &exp2[0], 0, sizeof(big_number) );
exp2[0].d[0] = 1;
exp2[0].len = 1;
for( i=1; i<=32; i++ ){
exp2[i] = exp2[i-1];
add( exp2[i], exp2[i-1] ); //ŒÓ·š±È³Ë·š¿ì
//mul( exp2[i], 2 );
}
}
//ŒÆËã (1+2^0)*(1+2^1)*(1+2^2)...(1+2^32)
void work()
{
int i;
big_number t;
memset( &ans, 0, sizeof(ans) );
memset( &t, 0, sizeof(t) );
t.d[0] = 1;
t.len = 1;
ans.d[0] = 1;
ans.len = 1;
for( i=0; i<=32; i++ ){
add( exp2[i], t ); // + 1
mul2( ans, exp2[i] );
}
print( ans );
}
int main()
{
int n=GetTickCount();
prepare();
work();
printf("\nTime used: %dmm\n", GetTickCount()-n );
system("pause");
return 0;
}
还可以优化的,特别是余数处理,我没时间去做。
哈哈,还是你的方法好啊。家里的机器的浏览器好像有问题,你的文章都看不全,只能看一小半
比起你的来,我的那个就太冗余了,400+行代码。
虽然也只用了16ms。但是毕竟我的机器比较好
对你越来越有兴趣·
请尝试用MMX或SSE指令内联做,你会得到更好的效率
struct big_number{
int d[64]; // 4*64 256位
int len;
}exp2[40], ans
从这里可以看出ans最大表示2^256-1的数。但是(1+2^0)*(1+2^1)*(1+2^2)…(1+2^32) > (2^0)*(2^1)*(2^2)…(2^32)=2^(32*33/2)=2^528.
我搞错了。ans能最大表示2^(256*8)-1
答案不是2^64-1么?把二进制的64个一转化为十进制不就可以了?
我用python写的4ms,只有7行
Windows的GetTickCount()计算不了比10ms小的时间。
阿阿。菜鸟我也边学边写个python的,看来结果和你一样的,写对了
hp@debian:~/Desktop$ time python ./aa.py
4190019477886606309869616409977680717118753725484183101420142516753342025884234435351687855236795051886469401755633755786814713540112118796616074978167792968750
real 0m0.019s
user 0m0.016s
sys 0m0.004s
"<" “>”没被替换,怪不得代码看起来不完整了
@osbin:已经更正,现在代码完整了,也好看了!!
注释变乱码了
不好意思。。。我在linux用gedit看gbk的文本文件,的确很烦恼。
注释都乱码了