P1045 [NOIP2003 普及组] 麦森数
题目传送门
#include
using namespace std;
/*
vector resize解析:
如果n小于当前容器的大小,则将内容减少到其前n个元素,
并删除超出范围的元素(并销毁它们)。
如果n大于当前容器的大小,则通过在末尾插入所需数量的元素来扩展内容,
以达到n的大小。如果指定了val,则将新元素初始化为val的副本,
否则将对它们进行值初始化。
如果n也大于当前容器容量,将自动重新分配已分配的存储空间。
请注意,此函数通过插入或擦除容器中的元素来更改容器的实际内容。
*/
//高精度乘法模板(高精乘高精)
vector mul(vector &A, vector &B) {
//只保留500个长度
if(A.size()>500) A.resize(500);
if(B.size()>500) B.resize(500);
int la = A.size(), lb = B.size();
vector C(la + lb + 10, 0);//提前申请结果所需的空间
for (int i = 0; i < la; i++)
for (int j = 0; j < lb; j++)
C[i + j] += A[i] * B[j];
for (int i = 0; i < C.size(); i++)
if (C[i] >= 10) {
C[i + 1] += C[i] / 10;
C[i] %= 10;
}
//处理前导0
while (C.size() > 1 && C.back() == 0)C.pop_back();
//只保留500个长度
if(C.size()>500) C.resize(500);
return C;
}
//快速幂+高精度 a^b
vector qmi(int a, int b) {
vector ans; //结果数组
ans.push_back(1); //底
vector A; //上一个依赖项
A.push_back(a);
while (b) {
if (b & 1) ans = mul(ans, A);
b >>= 1;
A = mul(A, A);
}
return ans;
}
int main() {
//计算 2^p-1的值
int p;
cin >> p;
vector A = qmi(2, p);//利用快速幂,计算2^p
//最后一位减去一个1,因为2^p最后一位肯定不是0,
// 所以减1不会产生借位,直接减去即可!
A[0]--;
//一共多少位
printf("%d\n", (int) (p * log10(2) + 1));
//每行输出50位,共输出10行,不足500位时高位补0
int cnt = A.size();
for (int i = 0; i < 500 - cnt; i++) A.push_back(0);
//倒着输出
for (int i = 500 - 1; i >= 0; i--) {
printf("%d", A[i]);
if (i % 50 == 0) printf("\n");
}
return 0;
}