练习-oj-麦森数

麦森数

问题描述:
形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
  
任务:输入P(1000<P<3100000),计算2P-1的位数及最后500位数字(用十进制高精度数表示)

思路

高精+快速幂

题解

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

int arr[1000500];
int ans[1000500];
int len=0;
//因为不想直接打平时用的高精结果把问题弄复杂的我是个屑
void times2();
void HAtimes();
void FastE(int n);

int main()
{
    int n=0,t=0;

    cin>>n;

    FastE(n);

    cout<<(int)(n*log10(2))+1<<endl;

    --arr[1];

    for(int i=500;i>=1;--i)
    {
        cout<<arr[i];
        ++t;
        if(t==50) {cout<<endl;t=0;}
    }

    return 0;
}

void FastE(int n)//快速幂
{
    bool flag=0;

    if(n==1) {arr[1]=2;len=1;return;}
    if(n%2==1) {flag=1;n--;}
    FastE(n/2);
    if(flag==1) {HAtimes();times2();}
    else {HAtimes();}
}

void HAtimes()//自己和自己相乘
{
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=len;++i)
        for(int j=1;j<=len;++j)
        {
            ans[i+j-1]+=arr[i]*arr[j];
            ans[i+j]+=ans[i+j-1]/10;
            ans[i+j-1]=ans[i+j-1]%10;
        }

        len=len*2;
        if(len>500)
        {
            len=500;
            for(int i=1;i<=len;++i)
            arr[i]=ans[i];
            return;
        }
        while(ans[len]==0) --len;
        for(int i=1;i<=len;++i)
            arr[i]=ans[i];
}

void times2()//和 2 相乘
{
    int tmp=0;

    for(int i=1;i<=len;++i)
    {
        arr[i]=arr[i]*2;
        arr[i]+=tmp;
        tmp=arr[i]/10;
        arr[i]=arr[i]%10;
    }
    if(tmp!=0) {len++;arr[len]=tmp;}
}

  • 不能用2连续相乘,会超时
  • 注意控制最后相乘的位数最大只能500,不然会超时

收获

  • 学会了快速幂
posted @ 2020-11-27 20:52  七铭的魔法师  阅读(170)  评论(0)    收藏  举报