码迷,mamicode.com
首页 > 其他好文 > 详细

梅森数 洛谷p1045

时间:2018-05-17 23:22:18      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:现在   efi   pre   ace   +=   pac   return   http   错误   

由于梅森数是一个巨大的数我们不能一个一个2来乘,由于只存最后五百位,我们就用高精乘的思想来做;

第一位算位数证明方式如下:

2?p 与 2?p-1具有相同位数,设2?p的位数等于k,我们知道10?n的位数为n+1,自己想想看,

我们只要把底数10换成2就行了,怎么用10的n次方来表示2呢,学过对数函数的应该知道,

技术分享图片所以原式子就变为技术分享图片,那么位数就为技术分享图片

#include<cmath>
#include<cstdio>
#include<iostream>
#define maxn 100000//压五位 不懂压位的可以自己看了解一下压位高精;
using namespace std;
int main()
{
    int p;
    scanf("%d",&p);
    printf("%d\n",(int)((p*log10(2.0))+1));//输出位数 int强制转换为整形;
    int s[110]={0},yu;//开个数组每个压五位不多说;
    yu=p%10;s[0]=1;//从1开始乘不多说,yu就是如同p为34这种褚步静就单独处理;
    p=p/10;//每次都从乘以2?10,这一步就是算2?p次方有多少个2?10,不难懂;
    for(int i=1;i<=p;i++)
    {
        for(int j=0;j<=100;j++)//s[j]<<10就是位运算 相当于乘以2^10;
          s[j]<<=10;//每位乘以1024这个我解释仔细一点比如一个三位数333如果乘以3,那么每一位都要乘以3,个位乘3变成9,十位也是一样;所以这里每5位都要乘以1024;
        for(int j=0;j<=100;j++)
        {
            if(s[j]>=maxn)
            {
                s[j+1]+=s[j]/maxn;//压位高精如果大于就进位
                s[j]%=maxn;
            }
        }
    }
    for(int i=1;i<=yu;i++)
   {
         for(int j=0;j<=100;j++)
                s[j]<<=1;//向左移一位就是乘以2
          for(int j=0;j<=100;j++)
        {
            if(s[j]>=maxn)
            {
                s[j+1]+=s[j]/maxn;//与上面一样的进位判断;
                s[j]%=maxn;
            }
        }
        
   }
    s[0]-=1;//梅森数最后要减1
    for(int i=99;i>=0;i--)
      {
        printf("%05d",s[i]);//输出因为压得五位所以位数不够就要补零这个知道压位方法的应该了解
        if(i%10==0)//没输出50位就提行输出格式
        printf("\n");      
      }
      return 0;
}

 

现在比较菜之前想了很久,若有错误请大佬们指正第一次认真发题解

梅森数 洛谷p1045

标签:现在   efi   pre   ace   +=   pac   return   http   错误   

原文地址:https://www.cnblogs.com/ltlt/p/9053677.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!