Loading

洛谷P1045 麦森数

题目描述

\(2^P - 1\)的后五百位,且输出\(2^P - 1\)的位数,其中\(1000<P<3100000\)

输出

第一行:十进制高精度数 \(2^{P}−1\) 的位数。

第2-11行:十进制高精度数 \(2^{P}−1\) 的最后500位数字。

(每行输出50位,共输出10行,不足500位时高位补0)

不必验证 \(2^{P}−1\)\(P\)是否为素数。

分析

1. 求数的位数

假设\(x = 2^P - 1\),即求\(x\)的位数,因为\(2^P\)的最后一位一定大于1。

所以\(2^P\)的位数与\(x\)的位数相同。

\(len = lg{x} + 1 = lg{2^P} + 1 = P*lg{2} + 1\)

例如100的长度为\(lg100 + 1 = 2 +1 = 3\)

所以长度的计算方法为

len = (int)(p * lg10(2)) + 1

2. 两个高精度数的乘法

const int N = 1e3 + 10; // 因为输出的长度为500, 500 + 500 = 1000

vector<int> mul(vector<int> A, vector<int> B) {
    vector<int> C(N, 0);
    for (i = 0; i < 500; i++)
		for (j = 0; j < 500; j++)
           	C[i + j] += C[i] * C[j];
   	for (j = 0; j < 500; j++) {
        C[j + 1] += C[j] / 10;
        C[j] = C[j] % 10;
    }
    return C;
}

3. 快速幂

使用快速幂对空间复杂度进行优化

int p; // p为输入的阶

vector<int> t(N, 0); // 保存2^1 2^2 2^4
vector<int> res(N, 0); // 结果
t[0] = 2; // 初始化
res[0] = 1;

while (p) {
	if (p & 1) // 如果p的2进制最后一个位为1
        res = mul(res, t);
    t = mul(t * t);
    p >>= 1;
}

4. 输出

    for (int i = 0, k = 499; i < 10; i++) {
        for (int j = 0; j < 50; j++, k--) {
            if (k) printf("%d", res[k]);
            else printf("%d", res[k] - 1);
        }
        puts("");
    }

完整代码

#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;

const int N = 1000 + 10;

vector<int> mul(vector<int> &A, vector<int> &B) {
    vector<int> C(N, 0);
    for (int i = 0; i < 500; i++)
        for (int j = 0; j < 500; j++)
            C[i + j] += A[i] * B[j];
            // printf("%d ", i + j);
    for (int j = 0; j < 500; j++) {
        C[j + 1] += C[j] / 10;
        C[j] %= 10;
    }
    return C;
}

int main() {
    int p;
    scanf("%d", &p);

    vector<int> res(N, 0);
    vector<int> t(N, 0);
    t[0] = 2; res[0] = 1;
    
    printf("%d\n", (int)(p * log10(2)) + 1);

    while (p) {
        if (p & 1)
            res = mul(res, t);
        t = mul(t, t);
        p >>= 1;
    }


    for (int i = 0, k = 499; i < 10; i++) {
        for (int j = 0; j < 50; j++, k--) {
            if (k) printf("%d", res[k]);
            else printf("%d", res[k] - 1);
        }
        puts("");
    }
    return 0;
}
posted @ 2020-11-15 14:17  mayapony  阅读(78)  评论(0编辑  收藏  举报