随手练——麦森数(高精度快速幂)
Posted czc1999
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了随手练——麦森数(高精度快速幂)相关的知识,希望对你有一定的参考价值。
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,时间的差别不是很大。
以上是关于随手练——麦森数(高精度快速幂)的主要内容,如果未能解决你的问题,请参考以下文章