形如 $2 ^ {P}-1$ 的素数称为麦森数,这时 $P$ 一定也是个素数。但反过来不一定,即如果 $P$ 是个素数, $2 ^ {P}-1$ 不一定也是素数。到 1998 年底,人们已找到了 37 个麦森数。最大的一个是 $P=3021377$ ,它有 $909526$ 位。麦森数有许多重要应用,它与完全数密切相关。
任务:从文件中输入 $P(1000 < P < 3100000)$,计算 $2 ^ {P}-1$ 的位数和最后 $500$ 位数字(用十进制高精度数表示)
文件中只包含一个整数 $P$(1000 < P < 3100000)
第一行:十进制高精度数 $2 ^ {P}-1$ 的位数。
第 2 - 11 行:十进制高精度数 $2 ^ {P}-1$ 的最后 500 位数字.(每行输出 50 位,共输出 10 行,不足 500 位时高位补 0 )
不必验证 $2 ^ {P}-1$ 与 $P$ 是否为素数。
1279
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
1. 题目难点:
2. 求 $2 ^ {P}-1$ 的位数
3. 高精度算法
在 C/C++ 中,$int$ 类型有 10 位,取值范围为:$-2147483648\sim2147483647$;$long\,long$ 类型有 19 位,取值范围为:$-9223372036854775808\sim9223372036854775807$
如果有两个 30 位的数字相乘,应该如何用计算机实现?
这就是高精度乘法的应用,以高精度加法举例,就是用数组存储数字每一位的数字,逐个运算,具体的算法可参考博客:高精度加、减、乘、除算法实现详解
在本题中,就是运用高精度乘法的原理实现二分快速幂过程。
4. 二分快速幂实现
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
//乘法开2倍长度
const int maxn = 1001;
int ans[maxn], b[maxn], carry[maxn], p;
void fun1(){
memset(carry, 0, sizeof(carry));
for(int i = 1;i <= 500;i++){
for(int j = 1;j <= 500;j++){
carry[i + j - 1] += ans[i] * b[j];
}
}
for(int i = 1;i <= 500;i++){
carry[i + 1] += carry[i] / 10;
carry[i] = carry[i] % 10;
}
memcpy(ans, carry, sizeof(ans));
}
void fun2(){
memset(carry, 0, sizeof(carry));
for(int i = 1;i <= 500;i++){
for(int j = 1;j <= 500;j++){
carry[i + j - 1] += b[i] * b[j];
}
}
for(int i = 1;i <= 500;i++){
carry[i + 1] += carry[i] / 10;
carry[i] = carry[i] % 10;
}
memcpy(b, carry, sizeof(b));
}
int main(){
int p;
cin >> p;
printf("%d\n", (int)( p * log10(2) ) + 1);
//赋初值
ans[1] = 1, b[1] = 2;
while(p){
if(p % 2){
fun1();
}
fun2();
p /= 2;
}
//题目要计算的是2 ^ {P} - 1
ans[1] -= 1;
for(int i = 500;i > 0;i--){
if(i != 500 && i % 50 == 0){
printf("\n%d", ans[i]);
}else{
printf("%d", ans[i]);
}
}
return 0;
}