题目情境#
题目链接:https://www.luogu.com.cn/problem/P1045 ↗
题目描述
形如 的素数称为麦森数,这时 一定也是个素数。但反过来不一定,即如果 是个素数, 不一定也是素数。到 1998 年底,人们已找到了 37 个麦森数。最大的一个是 ,它有 909526 位。麦森数有许多重要应用,它与完全数密切相关。
任务:输入 ,计算 的位数和最后 位数字(用十进制高精度数表示)
输入格式
文件中只包含一个整数
输出格式
第一行:十进制高精度数 的位数。
第 行:十进制高精度数 的最后 位数字。(每行输出 位,共输出 行,不足 位时高位补 )
不必验证 与 是否为素数。
输入 #1
1279
plaintext输出 #1
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087plaintext算法解析:#
麦森数:位数由 计算。后 500 位用高精度数组 + 快速幂:乘法按位逐位计算并进位,幂次按二进制拆分,最后个位减 1()。输出分 10 行,每行 50 位。
Python代码实现#
import sys
N = 500
def mul(a, b): # 高精度乘法
t = [0] * (N * 2)
for i in range(N):
for j in range(N):
t[i + j] += a[i] * b[j]
t[i + j + 1] += t[i + j] // 10
t[i + j] %= 10
return t
def quickpow(p): # 快速幂
a = [0] * N
res = [0] * N
a[0] = 2
res[0] = 1
while p:
if p & 1:
res = mul(res, a)
a = mul(a, a)
p >>= 1
res[0] -= 1 # 个位修正
return res
def main():
p = int(sys.stdin.readline())
# 输出位数
print(int(p * __import__('math').log10(2)) + 1)
res = quickpow(p)
for i in range(10):
start = N - 1 - i * 50
line_digits = res[start - 49:start + 1]
print(''.join(str(d) for d in reversed(line_digits)))
if __name__ == '__main__':
main()pythonC++代码实现#
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int N=500;
typedef vector<int> VI;
VI a(N),res(N);
int p;
VI mul(VI &a, VI &b){//高精度
VI t(N*2);
for(int i=0; i<N; i++)
for(int j=0; j<N; j++){
t[i+j] += a[i]*b[j];
t[i+j+1] += t[i+j]/10;
t[i+j] %= 10;
}
return t;
}
void quickpow(int p){//快速幂
res[0]=1, a[0]=2;
while(p){
if(p & 1) res = mul(res,a);
a = mul(a,a);
p >>= 1;
}
res[0]--; //个位修正
}
int main(){
cin >> p;
printf("%d\n",int(p*log10(2))+1);
quickpow(p);
for(int i=0, k=499; i<10; i++){
for(int j=0; j<50; j++, k--)
printf("%d",res[k]);
puts("");
}
return 0;
}c