You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

AcWing 416. 麦森数

首先考虑如何求位数。

我们发现在 10^k10^{k+1}1,(k≥0) 之间的数均有 k+1 位。因此对于任意正整数 x,它的位数是 ⌊log_{10}x⌋+1

而由于2的整次幂的末位数字不为0,因此 2^{P1} 的位数和 2^P 的位数相同,所以 2^{P1} 的位数是 ⌊log_{10}2^P⌋+1=⌊Plog_{10}2⌋+1

cmath库中有函数 log10(),直接使用即可。

然后考虑如何求最后500位数。

用快速幂,时间复杂度是 500^2logP=5×10^6

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;

// 高精度乘以高精度模板
int a[N], al;
int b[N], bl;
void mul(int a[], int &al, int b[], int &bl) {
    int c[N] = {0}, cl = al + bl;
    for (int i = 1; i <= al; i++)
        for (int j = 1; j <= bl; j++)
            c[i + j - 1] += a[i] * b[j];

    int t = 0;
    for (int i = 1; i <= al + bl; i++) {
        t += c[i];
        c[i] = t % 10;
        t /= 10;
    }
    memcpy(a, c, sizeof c);
    // 截取尾部有效长度500位
    al = 500;
    // 去除前导0
    while (al > 1 && a[al] == 0) al--;
}

// 快速幂+高精度 x^k
void qmi(int x, int k) {
    a[++al] = 1, b[++bl] = x; // 2 ^100 b[1]=2
    while (k) {
        if (k & 1) mul(a, al, b, bl);
        k >>= 1;
        mul(b, bl, b, bl);
    }
}

int main() {
    // 计算 2^p-1的值
    int p;
    cin >> p;
    // 利用快速幂计算2^p
    qmi(2, p);
    // 最后一位减去一个1因为2^k最后一位肯定不是0所以减1不会产生借位直接减去即可
    a[1]--;

    // 一共多少位
    printf("%d\n", (int)(p * log10(2) + 1));

    for (int i = 500; i; i--) {
        printf("%d", a[i]);
        // 该换行了,就是到了第二行的行首
        if ((i - 1) % 50 == 0) puts("");
    }
    return 0;
}