题目描述
形如 2^p−1 的素数称为麦森数,这时 p一定也是个素数。但反过来不一定,即如果 p 是个素数,2^p−1不一定也是素数。
到1998年底,人们已找到了37个麦森数。最大的一个是 p=3021377 ,它有 909526 位。麦森数有许多重要应用,它与完全数密切相关。
任务:输入p,计算 2^p−1的位数和最后500位数字(用十进制高精度数表示)
输入
一个整数P(1000<=p<=310000)。
输出
第一行:十进制高精度数 2^p−1 的位数。
第2-11行:十进制高精度数 2^p−1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
不必验证 2^p−1与p是否为素数。
输入样例 复制
1279
输出样例 复制
386 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000104079321946643990819252403273640855 38615262247266704805319112350403608059673360298012 23944173232418484242161395428100779138356624832346 49081399066056773207629241295093892203457731833496 61583550472959420547689811211693677147548478866962 50138443826029173234888531116082853841658502825560 46662248318909188018470682222031405210266984354887 32958028878050869736186900714720710555703168729087
萌新发题解,大佬勿喷。
-
输出位数
分析:2^p的末位>=2,所以2^p-1的位数与2^p相等。
10的位数是2,100是3,1000是4.则可推出对于任意一个数n
。其位数是lg(n)+1。
c++<cmath>库中的函数log10即可解决,位数是p*log10(2)+1。
2.求后500位
首先,p<=310000,用普通高精乘单精是绝对会TLE的。
所以,要用一个算法:快速幂
由数学定律可知 (a^b)^c=a^(b*c)
则2^p=(2^2)^p/2=((2^2)^2)^p/2/2。
当然,当p为奇数时怎么办?
简单,用一个数在p为奇数时乘一个2,同时乘上记录((2^2)^2)……的数
用另一个数在p不等于0时乘自己(2^2)^2……
然后只乘500位
废话不多说,上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int m,n,k;
int a[510],b[510],c[1110];
void quick_pow(int p)
{
int jw=0;
while(p>0)
{
if(p&1)//是2进制写法,可改成 if(p%2==1)
{// 当p是奇数时,把b数组里的数乘到a数组里,只要500位
jw=0;//高精乘高精,后500位
for(int i=1;i<=500;i++)
{
jw=0;
for(int j=1;j<=500;j++)
{
c[i+j-1]=a[i]*b[j]+c[i+j-1]+jw;
jw=c[i+j-1]/10;
c[i+j-1]%=10;
}
}
for(int i=1;i<=500;i++) //把结果放在a数组
a[i]=c[i];
memset(c,0,sizeof(c));// 记住一定要清零!!!
}
p>>=1; //2进制写法,可改成 p/=2
jw=0;
for(int i=1;i<=500;i++) //把b数组自乘一次,高精乘高精同上
{
jw=0;
for(int j=1;j<=500;j++)
{
c[i+j-1]=b[i]*b[j]+c[i+j-1]+jw;
jw=c[i+j-1]/10;
c[i+j-1]%=10;
}
}
for(int i=1;i<=500;i++)
b[i]=c[i];
memset(c,0,sizeof(c));
}
a[1]--;//记住要减一!!!
}
int main()
{
cin>>n;
double k=log10(2);
int wei=k*n+1;
cout<<wei<<endl;//输出位数
a[1]=1;
b[1]=2;//千万不能忘了初始化!!!
int sum=0;
quick_pow(n);
for(int i=500;i>=1;i--)
{
sum++;//计数器,为了一行输出50个
cout<<a[i];
/**/if(sum==50)
{
sum=0; //以华丽的输出结尾
cout<<endl;
}
}
return 0;
}
点一个攒呗???