P1045 [NOIP2003 普及组] 麦森数

// Problem: P1045 [NOIP2003 普及组] 麦森数
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1045
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// User: Pannnn

#include <bits/stdc++.h>

using namespace std;

/*
    2^p与2^p-1有相同的位数,2的次方满足了最后一位不为0的要求,所以减1后位数不会改变。
    令k = 2^p,由于10^n的位数为n+1,将k改写为以10为底的数。
    10^(log(10)2) = 2
    k = ( 10 ^ (log(10)2) ) ^ p
    位数就是log(10)2 * p + 1
    
    在算乘法时,不能完全告警,数据太长会超时
*/

vector<int> add(vector<int> a, vector<int> b) {
    vector<int> res;
    int pre = 0;
    for (int i = 0; i < a.size() || i < b.size(); ++i) {
        if (i < a.size()) {
            pre += a[i];
        }
        if (i < b.size()) {
            pre += b[i];
        }
        res.push_back(pre % 10);
        pre /= 10;
    }
    if (pre) {
        res.push_back(pre);
    }
    return res;
}

vector<int> mulByInt(vector<int> a, int b, int i) {
    vector<int> res(i);
    int pre = 0;
    for (int i = 0; i < a.size(); ++i) {
        pre += a[i] * b;
        res.push_back(pre % 10);
        pre /= 10;
    }
    while (pre) {
        res.push_back(pre % 10);
        pre /= 10;
    }
    return res;
}

vector<int> mul(vector<int> a, vector<int> b) {
    vector<int> res;
    
    for (int i = 0; i < b.size(); ++i) {
        vector<int> tmp = mulByInt(a, b[i], i);
        res = add(res, tmp);
    }
    return res;
}

vector<int> getValue(int p) {
    vector<int> res(1, 1);
    vector<int> tmp(1, 2);
    while (p) {
        if (p & 1) {
            res = mul(res, tmp);
        }
        tmp = mul(tmp, tmp);
        tmp.resize(500);
        res.resize(500);
        p >>= 1;
    }
    
    return res;
}

vector<int> subByOne(vector<int> a) {
    int pre = 1;
    for (int i = 0; i < a.size(); ++i) {
        if (a[i] < pre) {
            a[i] = 9;
        } else {
            --a[i];
            break;
        }
    }
    return a;
}

int main() {
    int p;
    cin >> p;
    
    vector<int> res = getValue(p);
    cout << (int)(log10(2) * p + 1) << endl;
    res = subByOne(res);
    res.resize(500);
    for (int i = res.size() - 1; i >= 0; --i) {
        cout << res[i];
        if (i % 50 == 0) {
            cout << endl;
        }
    }
    return 0;
}
上一篇:【算法和数据结构】排序和堆


下一篇:洛谷 P1618 三连击(升级版)