P1045 麦森数

P1045 麦森数

题目描述

形如2^{P}-12
P
−1的素数称为麦森数,这时PP一定也是个素数。但反过来不一定,即如果PP是个素数,2^{P}-12
P
−1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。

任务:从文件中输入PP(1000<P<31000001000<P<3100000),计算2^{P}-12
P
−1的位数和最后500位数字(用十进制高精度数表示)

输入格式:

文件中只包含一个整数PP(1000<P<31000001000<P<3100000)

输出格式:

第一行:十进制高精度数2^{P}-12
P
−1的位数。

第2-11行:十进制高精度数2^{P}-12
P
−1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)

不必验证2^{P}-12
P
−1与PP是否为素数。

输入样例#1:

1279

输出样例#1:

386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087

解题思路

分两问
第一问:利用数学公式–>(n*lg 2)+1
第二问:高精度快速幂,题目要求后500位,c++里应该没有什么数据类型可以保存,所以利用辅助数组,一样的利用快速幂的模板。思路大概就这样,迷糊的话,看代码就清楚了,分步做的QWQ。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int a[1010],b[1010],s[1010];
void mss1() 
{
    memset(s,0,sizeof(s));
    for(int i=1; i<=500; i++)
        for(int j=1; j<=500; j++)//先乘后进位
            s[i+j-1]+=a[i]*b[j];
    for(int i=1; i<=500; i++)
    {
        s[i+1]+=s[i]/10;
        s[i]%=10;
    }
    memcpy(a,s,sizeof(a));
}
void mss2() //更新幂
{
    memset(s,0,sizeof(s));
    for(int i=1; i<=500; i++)
        for(int j=1; j<=500; j++)//先乘后进位
            s[i+j-1]+=b[i]*b[j];
    for(int i=1; i<=500; i++)
    {
        s[i+1]=s[i]/10;
        s[i]%=10;
    }
    memcpy(b,s,sizeof(b));
}
int main()
{
    int p;
    cin>>p;
    printf("%d\n",(int)(log10(2)*p+1));
    a[1]=1;
    b[1]=2;
    while(p!=0)//开始快速幂
    {
        if(p%2==1) mss1();//由于有500位,所以使用辅助数组;
        p=p/2;//就是p/2
        mss2();//相当于2*2,4*2,8*2,由于p太大了,所以需要辅助数组来完成
    }
    a[1]-=1;
    for(int i=500; i>=1; i--)
        if(i!=500&&i%50==0) printf("\n%d",a[i]);
        else printf("%d",a[i]);
    return 0;
}

做作业的小学生路过,勿扰!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值