Files
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

73 lines
2.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## [$AcWing$ $416$. 麦森数](https://www.acwing.com/problem/content/description/418/)
### 一、考虑如何求位数
我们发现在 $x \in (10^k∼10^{k+1}−1)$ 之间的数均有 $k+1$ 位。对于正整数 $x$,位数等于 $⌊log_{10}x⌋+1$。
而由于$2$的整次幂的末位数字不为$0$,减1并不会使得它位数发生变化,因此 $2^{P−1}$ 的位数和 $2^P$ 的位数相同,所以 $2^{P}-1$ 的位数等于$2^{P}$,等于$⌊log_{10}2^P⌋+1=⌊Plog_{10}2⌋+1$。
$cmath$库中有函数 $log10()$,直接使用即可。
### 二、考虑如何求最后$500$位数
用快速幂,时间复杂度是 $500^2logP=5×10^6$
```cpp {.line-numbers}
#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;
}
```