蓝桥杯 算法训练 麦森数 By Assassin (数学+模拟)

问题描述
  形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
  任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)
输入格式
  文件中只包含一个整数P(1000<P<3100000)
输出格式
  第一行:十进制高精度数2P-1的位数。
  第2-11行:十进制高精度数2P-1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
  不必验证2P-1与P是否为素数。
样例输入
1279
样例输出
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087

思路:题目本身的难点就是一个数学知识,麦森数长度怎么求,网上看到别人的思路才知道

length=plog10(2)+1

至于求后500位,就是一个大数乘法模拟,乘法要用快速幂,我用的数组加string串模拟。注意的就是数组直接用500长度的就行!不用结果是否超过500.知识点都不难(除了数学…)就是组合一下。
再次体会到了数学的力量啊…

#include<bits/stdc++.h>
using namespace std;
string quick[26];
string multi(string a,string b){
    int temp1[502]={0},temp2[501]={0},answer[501]={0};
    int lena=a.size(),lenb=b.size();
    for(int i=1;i<=lena;i++){
        if(i>500) break;
        temp1[i]=(a[lena-i]-'0');
    }
    for(int i=1;i<=lenb;i++){
        if(i>500) break;
        temp2[i]=(b[lenb-i]-'0');
    }
    for(int i=1;i<=500;i++){
        for(int j=1;j<=500;j++){
            if(i+j-1<=500){
                answer[i+j-1]+=temp1[i]*temp2[j];
            }
        }
    }
    for(int i=1;i<=500;i++){
        answer[i+1]+=(answer[i])/10;
        answer[i]%=10;
    }
    string ans="";
    for(int i=500;i>=1;i--){
        ans+='0'+answer[i];
    } 
    return ans;
}


int main(){
    int n;
    quick[0]="2";
    for(int i=1;i<=25;i++){
        quick[i]=multi(quick[i-1],quick[i-1]);
    }
    scanf("%d",&n);
    string ans="1";
    for(int i=0;i<=25;i++){
        if(n>>i&1){
            ans=multi(ans,quick[i]);
        }
    }
//  cout<<ans<<endl;
    for(int i=500;i>=3;i--){
        if(ans[i]>='0'){
            ans[i]--;
            break;
        }
        else{
            ans[i]='9';
        }
    }
    cout<<(int)(n*log10(2))+1<<endl;
    for(int i=0;i<10;i++){
        for(int j=0;j<50;j++){
            cout<<ans[i*50+j];
        }
        cout<<endl;
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值