【洛谷P1045】麦森数

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

题面就不贴了,地址如上。

本题有两个很妙的地方:

一,用log算位数:

$\because 10^n 的位数是n+1$

$\therefore 我们想办法把 2^p-1转化为10^n的形式$,其中$2^p与2^p-1的位数相同(很显然),所以我们只用求2^p即可$

又$\because10^{lg2}=2$

$\therefore 10^{p\times lg2}=2^{p}$

$\therefore 位数即为p\times lg2+1$

二,用快速幂的思想:

因为出现了很大的p,而且只要求后500位,所以我们直接高精度快速幂,只管后500位,其他不变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const int maxn=510;
int p,a[maxn],c[maxn];

void mul1()//a*c
{
int tmp[maxn],i,j;
memset(tmp,0,sizeof(tmp));
for (i=1;i<=500;i++)
for (j=1;j<=500;j++)
if (i+j-1<=500)
{
tmp[i+j-1]+=a[i]*c[j];
tmp[i+j]+=tmp[i+j-1]/10;
tmp[i+j-1]%=10;
}
memcpy(c,tmp,sizeof(c));
}

void mul2()//a*a
{
int tmp[maxn],i,j;
memset(tmp,0,sizeof(tmp));
for (i=1;i<=500;i++)
for (j=1;j<=500;j++)
if (i+j-1<=500)
{
tmp[i+j-1]+=a[i]*a[j];
tmp[i+j]+=tmp[i+j-1]/10;
tmp[i+j-1]%=10;
}
memcpy(a,tmp,sizeof(a));
}

int main()
{
int i,j;
scanf("%d",&p);
printf("%d\n",(int)(1.0*p*log10(2))+1);
c[1]=1;
a[1]=2;
for (;p;p>>=1)
{
if (p&1)
mul1();
mul2();
}
c[1]--;
for (i=1;i<=10;i++)
{
for (j=500-(i-1)*50;j>=500-i*50+1;j--)
printf("%d",c[j]);
puts("");
}
return 0;
}
显示 Gitment 评论