一、题目链接
二、题目大意
输入
P
P
P,计算
2
P
−
1
2^P-1
2P−1的位数和最后
500
500
500位数字(用十进制高精度数表示)
数据范围:
1000
<
P
<
3100000
1000<P<3100000
1000<P<3100000
三、题目分析:
- 实际上和麦森数没啥关系
- 因为数量级的问题,此题只能采用高精度和快速幂。
- 2 n − 1 2^n -1 2n−1在十进制下位数和 2 n 2^n 2n 相同,因为 2 2 2的整数次幂的尾数为 2 , 4 , 8 , 6 2,4,8,6 2,4,8,6一定大于 1 1 1,所以只需计算 2 n 2^n 2n的位数即可。
- 2 n = 1 0 n l g 2 2^n =10^{nlg2} 2n=10nlg2,所以最终的位数为 ⌊ n l g 2 ⌋ \lfloor nlg2\rfloor ⌊nlg2⌋。
- 最后得到 2 n − 1 2^n-1 2n−1时的减法也一定要用高精度。
四、正解程序:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
int P,fina[1010],ans[1010];
void mul(int *a,int *b)
{
memset(fina,0,sizeof(fina));
for(int i=1;i<=500;i++)
{
for(int j=1;j<=500;j++)
{
if(j+i-1>1000)
continue;
int temp=fina[j+i-1]+a[i]*b[j];
fina[j+i]+=temp/10;
fina[j+i-1]=temp%10;
}
}
for(int i=1;i<=1010;i++)
a[i]=fina[i];
}
void quickmi()
{
int ans[1010],a[1010];
memset(ans,0,sizeof(ans));
memset(a,0,sizeof(a));
ans[1]=1;a[1]=2;
while(P)
{
if(P&1)
mul(ans,a);
P>>=1;
mul(a,a);
}
int times=0;
for(int i=1;i<=500;i++)
{
if(ans[i]<=0)
{
ans[i+1]--;
ans[i]=9;
}
else
{
ans[i]--;
break;
}
}
for(int i=500;i>=1;i--)
{
++times;
printf("%d",ans[i]);
if(times==50)
{
printf("\n");
times=0;
}
}
}
int main()
{
scanf("%d",&P);
printf("%d\n",(int)(log10(2)*P+1));
quickmi();
return 0;
}