练习-oj-麦森数
麦森数
问题描述:
形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
任务:输入P(1000<P<3100000),计算2P-1的位数及最后500位数字(用十进制高精度数表示)
思路
高精+快速幂
题解
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int arr[1000500];
int ans[1000500];
int len=0;
//因为不想直接打平时用的高精结果把问题弄复杂的我是个屑
void times2();
void HAtimes();
void FastE(int n);
int main()
{
int n=0,t=0;
cin>>n;
FastE(n);
cout<<(int)(n*log10(2))+1<<endl;
--arr[1];
for(int i=500;i>=1;--i)
{
cout<<arr[i];
++t;
if(t==50) {cout<<endl;t=0;}
}
return 0;
}
void FastE(int n)//快速幂
{
bool flag=0;
if(n==1) {arr[1]=2;len=1;return;}
if(n%2==1) {flag=1;n--;}
FastE(n/2);
if(flag==1) {HAtimes();times2();}
else {HAtimes();}
}
void HAtimes()//自己和自己相乘
{
memset(ans,0,sizeof(ans));
for(int i=1;i<=len;++i)
for(int j=1;j<=len;++j)
{
ans[i+j-1]+=arr[i]*arr[j];
ans[i+j]+=ans[i+j-1]/10;
ans[i+j-1]=ans[i+j-1]%10;
}
len=len*2;
if(len>500)
{
len=500;
for(int i=1;i<=len;++i)
arr[i]=ans[i];
return;
}
while(ans[len]==0) --len;
for(int i=1;i<=len;++i)
arr[i]=ans[i];
}
void times2()//和 2 相乘
{
int tmp=0;
for(int i=1;i<=len;++i)
{
arr[i]=arr[i]*2;
arr[i]+=tmp;
tmp=arr[i]/10;
arr[i]=arr[i]%10;
}
if(tmp!=0) {len++;arr[len]=tmp;}
}
坑
- 不能用2连续相乘,会超时
- 注意控制最后相乘的位数最大只能500,不然会超时
收获
- 学会了快速幂

浙公网安备 33010602011771号