//
G - 麦森数
形如2p-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数。2p-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
任务:从文件中输入P (1000<P<3100000) ,计算2p-1的位数和最后500位数字(用十进制高精度数表示)
Input
文件中只包含一个整数P(1000<P<3100000)
Output
第1行:十进制高精度数2p-1的位数。
第2-11行:十进制高精度数2p-1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
不必验证2p-1与P是否为素数。
Sample Input
1279
Sample Output
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
//
题意:计算2^p-1 的位数 求最后 500 位 不足的补 0
//
题解:
01 普通 大数*小数 超时 使用 '快速幂' 优化算法
02 位数推导
10^a>2^p-1>=10^a-1
10a+1>2^p>=10a-1+1 ( +1 )
log10(10^a+1)>log10(2^p)>=log10(10^a-1+1) ( 对10取对数 )
a>[p*log10(2)]>=a-1 ( 化简 )
[p*log10(2)]+1>=a>[p*log10(2)] ( 转化 )
so a=[p*log10(2)]+1
快速幂
// 麦森数
#include<bits/stdc++.h>
using namespace std;
const int MAXN=500;
void bigmul( int a[],int b[] )
{
int i,j,c[ MAXN+11 ];
memset( c,0,sizeof(c) );
for( i=0;i<MAXN+5;i++ )
{
for( j=0;i+j<MAXN+5;j++ ) // 只保留500位
{
c[i+j]+=a[j]*b[i];
}
}
for( i=0;i<MAXN;i++ )
{
c[i+1]+=c[i]/10; //
a[i]=c[i]%10;
}
}
int main()
{
int ans[ MAXN+11 ],sq[ MAXN+11 ];
int p,pos,cnt,i;
scanf("%d",&p);
pos=(int)( log10(2)*p+1 );
printf("%d\n",pos);
// 初始化 不足500位时高位补0
memset( ans,0,sizeof(ans) );
memset( sq,0,sizeof(sq) );
ans[0]=1; sq[0]=2;
// 快速幂
while( p )
{
if( p&1 ) bigmul( ans,sq ); // int/2 向下取整 特殊处理奇数
bigmul( sq,sq ); // 降指
p>>=1;
}
ans[0]--; // (2^p-1)的后500位数
cnt=0; //
for( i=MAXN-1;i>=0;i-- ) //
{
cnt++;
printf("%d",ans[i]);
if( cnt==50 ) { cnt=0; printf("\n"); }
}
printf("\n");
return 0;
}
// 麦森数 ( 递归 )
#include<bits/stdc++.h>
using namespace std;
const int MAXN=500;
int a[ MAXN+11 ],b[ MAXN+11 ];
void solve( int p )
{
if( p ) solve( p>>1 );
else return;
int i,j;
for( i=1;i<=MAXN+5;i++ )
{
// i+j<=MAXN+5 i+j==MAXN 时 还不能停下
for( j=1;i+j<=MAXN+5;j++ )
{
if( p&1 ) a[ i+j-1 ]+=b[i]*b[j]*2;
else a[ i+j-1 ]+=b[i]*b[j];
}
}
for( i=1;i<=MAXN;i++ )
{
a[i+1]+=a[i]/10;
b[i]=a[i]%10;
}
memset( a,0,sizeof(a) );
}
int main()
{
int p,i;
scanf("%d",&p);
printf("%d\n",(int)( log10(2)*p+1 ));
memset( a,0,sizeof(a) );
memset( b,0,sizeof(b) );
b[1]=1;
solve(p);
for( i=MAXN;i>=2;i-- )
{
printf("%d",b[i]);
if( i%50==1 ) printf("\n");
}
printf("%d\n",b[i]-1);
return 0;
}