1. 程式人生 > >梅森數 洛谷p1045

梅森數 洛谷p1045

高精 左移 clu 了解 efi 第一次 for 一位 std

由於梅森數是一個巨大的數我們不能一個一個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