P1045 [NOIP 2003 普及组] 麦森数 - 题解
P1045 [NOIP 2003 普及组] 麦森数
题目描述
形如 $2^{P}-1$ 的素数称为麦森数,这时 $P$ 一定也是个素数。但反过来不一定,即如果 $P$ 是个素数,$2^{P}-1$ 不一定也是素数。到 1998 年底,人们已找到了 37 个麦森数。最大的一个是 $P=3021377$,它有 909526 位。麦森数有许多重要应用,它与完全数密切相关。
任务:输入 $P(1000<P<3100000)$,计算 $2^{P}-1$ 的位数和最后 $500$ 位数字(用十进制高精度数表示)
输入格式
文件中只包含一个整数 $P(1000<P<3100000)$
输出格式
第一行:十进制高精度数 $2^{P}-1$ 的位数。
第 $2\sim 11$ 行:十进制高精度数 $2^{P}-1$ 的最后 $500$ 位数字。(每行输出 $50$ 位,共输出 $10$ 行,不足 $500$ 位时高位补 $0$)
不必验证 $2^{P}-1$ 与 $P$ 是否为素数。
输入输出样例 #1
输入 #1
1279
输出 #1
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
说明/提示
【题目来源】
NOIP 2003 普及组第四题
代码题解
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
int p;
string sub(string a,string b){
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
while(b.length()<a.length())b+='0';
for(int i=0;i<a.length();i++){
a[i]-='0';
}
for(int i=0;i<b.length();i++){
b[i]-='0';
}
int alen = a.length(),blen = b.length();
for(int i=0;i<alen;i++){
if(a[i]-b[i]<0){
a[i+1]-=1;
a[i]+=10;
}
a[i]-=b[i];
}
reverse(a.begin(),a.end());
for(int i=0;i<alen;i++){
a[i]+='0';
}
stringstream s;
for(int i=0,flag=1;i<alen;i++){
if(flag&&a[i]!='0'){
flag=0;
}
if(flag)continue;
s<<a[i];
}
return s.str();
}
string mul(string a,string b){
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
for(int i=0;i<a.length();i++){
a[i]-='0';
}
for(int j=0;j<b.length();j++){
b[j]-='0';
}
int c[505]={0};//<-----------一定是int类型,char会爆127
for(int i=0;i<a.length();i++){
for(int j=0;j<b.length();j++){
if(i+j>=500)continue;
c[i+j] += a[i]*b[j];
}
}
for(int i=0;i<500;i++){
c[i+1]+=c[i]/10;
c[i]%=10;
}
stringstream s;
for(int i=499,flag=1;i>=0;i--){
if(flag&&c[i]!=0){
flag=0;
}
if(flag)continue;
s<<(char)(c[i]+'0');
}
return s.str().length()==0?"0":s.str();
}
const int N = 3100010;
string power(string a,int b){
if(!b)return "1";
string res;
if(b&1){
res = power(a,b/2);
res = mul(a,mul(res,res));
}else{
res = power(a,b/2);
res = mul(res,res);
}
return res;
}
int main(){
cin>>p;
string ans = sub(power("2",p),"1");
long long bit = floor(p*log10(2)+1e-8)+1;//<--------要用下取整1e-8意思就是向上加0.00000001,
// 然后加一就是答案,如果只是用浮点数舍去.0的位数,那么容易造成精度误差,
// 最后得到60分。把精度解决,就能拿到满分了。调了半天结果居然是这个地方的问题,我真是服了。
cout<<bit;
for(int i=0,j=0;i<500;i++){
if(i%50==0){
cout<<endl;
}
if(i<500-ans.length()){
cout<<"0";
}else{
cout<<ans[j++];
}
}
}

浙公网安备 33010602011771号