随手练——麦森数(高精度快速幂)

https://www.luogu.org/problemnew/show/P1045

第一步:求位数

第二步:高精度快速幂的实现

第一版:

用vector做的,中间把超过500位的去除,但是实际跑起来比较慢

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <algorithm>
using namespace std;

int bits;

void carry(vector<int>& a) {
    for (int i = 0; i < a.size(); i++) {
        if (i != a.size() - 1)a[i + 1] += a[i] / 10;
        else if (a[i] >= 10)a.push_back(a[i] / 10);
        a[i] %= 10;
    }
    while (a.size() > 500) {
        a.pop_back();
        //bits++;
    }
}

void multi(vector<int>& a, vector<int>b) {
    int k = 0;
    vector<int>res(a.size());
    for (int i = 0; i < b.size(); i++) {
        for (int j = 0; j < a.size(); j++) {
            if (k + j >= res.size())
                res.push_back(0);
            res[k + j] += a[j] * b[i];
        }
        k++;
    }
    carry(res);

    a = res;
}

void quick_power(vector<int>& a, int k) {
    vector<int>res;
    res.push_back(1);
    while (k) {
        if (k & 1)
            multi(res, a);
        k >>= 1;
        if(k)
        multi(a, a);
    }
    a = res;
}

int main() {
    int p, k = 1;
    cin >> p;
    vector<int>a, b;
    a.push_back(2);
    cout << (int)(log10(2) * p + 1) << endl;
    quick_power(a, p);

    if (a.size() < 500) {
        for (int i = a.size(); i < 500; i++, k++) {
            cout << 0;
            if (k % 50 == 0)cout << endl;
        }
    }
    a[0] -= 1;

    for (int i = a.size() - 1; i >= 0; i--, k++) {
        cout << a[i];
        if (k % 50 == 0)cout << endl;
    }
    cout << endl;
    return 0;
}

第二版:

直接用int数组,循环全都是到500停止,锁死了时间上限,当p大的时候,确实非常快,不过可读性稍微差了一点。

#include <iostream>
#include <string.h>
#include <math.h>

using namespace std;

int a[1001] = { 2 }, b[1001], res[1001], temp[1001];

void carry(int *arr) {
    for (int i = 0; i < 500; i++) {
        arr[i + 1] += arr[i] / 10;
        arr[i] %= 10;
    }
}

void multi(int* a, int* b, int* res) {
    memset(temp, 0, sizeof(temp));
    for (int i = 0; i < 500; i++) {
        for (int j = 0; j < 500; j++) {
            temp[i + j] += a[j] * b[i];
        }
    }
    carry(temp);
    memcpy(res, temp, sizeof(temp));
}

void quick_power(int k) {
    res[0] = 1;
    while (k) {
        if (k & 1)
            multi(res, a, res);
        k >>= 1;
        if (k)
            multi(a, a, a);
    }
}

int main() {
    int p, k = 1;
    cin >> p;
    int bits = (int)(log10(2) * p + 1);
    cout << bits << endl;
    quick_power(p);
    //2^n次方,不可能为0,所以可以直接减1
    res[0] -= 1;
    for (int i = 499; i >= 0; i--, k++) {
        cout << res[i];
        if (k % 50 == 0)cout << endl;
    }
    cout << endl;
    return 0;
}

很奇怪的是,测试数据中一个很大的p值,本地跑起来,第一版要等5s左右,第二版几乎瞬间就出来了,交OJ,时间的差别不是很大。

原文地址:https://www.cnblogs.com/czc1999/p/10800633.html

时间: 2024-10-02 08:51:48

随手练——麦森数(高精度快速幂)的相关文章

vijos - P1223麦森数 (高精度乘法 + 分治 + python)

P1223麦森数 Accepted 标签:NOIP普及组2003[显示标签] 描述 形如2^P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2^P-1的位数和最后500位数字(用十进制高精度数表示) 格式 输入格式 文件中只包含一个整数P(10

【日常学习】【高精快速幂】codevs1087 麦森数题解

题目描述 Description 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示) 输入描述 Input Description 文件中只包含一个整数P(1000<P<31

快速幂+分治(洛谷P1045 麦森数 noip2003)

形如的素数称为麦森数,这时一定也是个素数.但反过来不一定,即如果是个素数,不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入(),计算的位数和最后500位数字(用十进制高精度数表示) 输入格式: 文件中只包含一个整数() 输出格式: 第一行:十进制高精度数的位数. 第2-11行:十进制高精度数的最后500位数字.(每行输出50位,共输出10行,不足500位时高位补0) 不必验证与是否为素数.

【noip2003】 麦森数

题目描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示) 输入 文件中只包含一个整数P(1000<P<3100000) 输出 第一行:十进制高精度数2P-1的位数. 第2

洛谷OJ P1045 麦森数 解题报告

洛谷OJ P1045 麦森数 解题报告 by MedalPluS   题目描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)   输入描述   文件中只包含一个整数P(1000&l

麦森数

题目描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示) 输入输出格式 输入格式: 文件中只包含一个整数P(1000<P<3100000) 输出格式: 第一行:十进制高精

NOIP200304麦森数

试题描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示) 输入 文件中只包含一个整数P(1000<P<3100000) 输出 第一行:十进制高精度数2P-1的位数.第2-

算法训练 麦森数

问题描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示) 输入格式 文件中只包含一个整数P(1000<P<3100000) 输出格式 第一行:十进制高精度数2P-1的位数

2003麦森数

题目描述 Description 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示) 输入描述 Input Description 文件中只包含一个整数P(1000<P<31