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++];
        }
    }
}

posted @ 2026-11-01 11:28  ysMip  阅读(3)  评论(0)    收藏  举报