问题描述
形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)
任务:从文件中输入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是否为素数。
第2-11行:十进制高精度数2P-1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
不必验证2P-1与P是否为素数。
解题思路:对于其位数,直接有数学定理为,int(log10(2)*p+1)
解决2的P次方计算方法如下:
1、用数组作为数据结构进行高精度计算
2、用二分快速幂进行计算
代码如下:
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 using namespace std; 5 int a[502]={0},b[502]; 6 void cal(){ 7 int i,j,k; 8 memset(b,0,sizeof(b)); 9 for(i=1;i<=500;i++){//对应相乘 10 for(j=1,k=i;j<=500;j++){ 11 b[k]=b[k]+a[i]*a[j]; 12 k++; 13 if(i==501) break;//乘完第五百位就break,题目要求,再多无益。 14 } 15 } 16 for(i=1;i<=500;i++){//处理进位 17 if(b[i]>=10){ 18 b[i+1]+=b[i]/10; 19 b[i]=b[i]%10; 20 } 21 a[i]=b[i];//更新快速幂 22 } 23 } 24 void recur(int p){ 25 if(p==1 || p==0){ 26 a[1]=2; 27 return; 28 } 29 else{ 30 recur(p/2); 31 cal(); 32 if(p%2==1){//奇数再乘以2 33 memset(b,0,sizeof(b)); 34 for(int i=1;i<=500;i++){//对应相乘 35 b[i]+=2*a[i]; 36 } 37 } 38 for(int i=1;i<=500;i++){//处理进位 39 if(b[i]>=10){ 40 b[i+1]+=b[i]/10; 41 b[i]=b[i]%10; 42 } 43 a[i]=b[i];//更新快速幂 44 } 45 } 46 } 47 int main(){ 48 int p; 49 cin>>p; 50 cout<<int(log10(2)*p+1); 51 recur(p); 52 a[1]-=1; 53 for(int i=500; i>0; i--){ 54 if(i%50 == 0){ 55 printf("\n"); 56 } 57 printf("%d", a[i]); 58 59 } 60 return 0; 61 }