题目描述
形如2^{P}-12P−1的素数称为麦森数,这时PP一定也是个素数。但反过来不一定,即如果PP是个素数,2^{P}-12P−1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。
任务:从文件中输入PP(1000<P<31000001000<P<3100000),计算2^{P}-12P−1的位数和最后500位数字(用十进制高精度数表示)
输入输出格式
输入格式:
文件中只包含一个整数PP(1000<P<31000001000<P<3100000)
输出格式:
第一行:十进制高精度数2^{P}-12P−1的位数。
第2-11行:十进制高精度数2^{P}-12P−1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
不必验证2^{P}-12P−1与PP是否为素数。
输入输出样例
输入样例#1: 复制
1279
输出样例#1: 复制
386 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000104079321946643990819252403273640855 38615262247266704805319112350403608059673360298012 23944173232418484242161395428100779138356624832346 49081399066056773207629241295093892203457731833496 61583550472959420547689811211693677147548478866962 50138443826029173234888531116082853841658502825560 46662248318909188018470682222031405210266984354887 32958028878050869736186900714720710555703168729087
思路:
1、计算位数的时候可以使用log10(x)+1来计算位数 ------> 这个就不过多介绍了
2、计算后500位的时候可以用快速幂来做,我们可以设置三个数组,一个用来存放2的幂次,一个用来存放计算出来的,一个用于存放将来读取数据的数组
代码:
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#include<math.h>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define PI acos(-1)
#define close ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define open #ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout); #endif
using namespace std;
typedef long long ll;
const double pai=3.141592653589793238462643383279;
const int MAX_N = 1000000+50;
const int INF = 0x3f3f3f3f;
const int maxn = 500;
const double EPS = 1e-10;
const ll INF_ll = 0x7fffffffffffffff;
ll mod = 1e9+7;
/*
不要放弃
Don't give up
*/
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
inline void Out(int a)
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
int r[maxn],a[maxn],c[maxn],p;
void Mul()
{
//这里是循环写入 对后500位进行赋值
for(int i = 0; i <= maxn-1; i++)
{
for(int j = 0; j <= maxn-1; j++)
{
if(i+j <= maxn-1)
{
c[i+j] += r[i]*a[j];
//下边是考虑进位的事情
while(c[i+j] >= 10)
{
c[i+j] -= 10;
if(i+j+1 <= maxn-1) c[i+j+1] += 1; //这里不能越界
}
}
}
}
//新函数 很实用
memcpy(r,c,sizeof(r));
memset(c,0,sizeof(c));
}
void Mul1()//其实2和1一样,只是改了几小处
{
for(int i=0;i<=maxn-1;i++)
{
for(int j=0;j<=maxn-1;j++)
{
if(i+j<=maxn-1)
{
c[i+j]+=a[i]*a[j];
while(c[i+j]>=10)
{
c[i+j]-=10;
if(i+j+1<=maxn-1) c[i+j+1]+=1;
}
}
}
}
//a在不断改变
memcpy(a,c,sizeof(a));
memset(c,0,sizeof(c));
}
void Qpow(int b)
{
while(b)
{
//cout<<(b&1)<<endl;
if(b&1) Mul();
Mul1();
b>>=1;
}
}
int main()
{
close
cin>>p;
r[0] = 1;
a[0] = 2;
Qpow(p);
r[0] -= 1; // 最后一位需要减一 而且这里也没有出现比1小的情况
int ans = p*log10(2)+1;
cout<<ans<<endl;
for(int i = maxn-1; i >= 0; i--){
cout<<r[i];
if(i%50 == 0) cout<<endl;
}
cout<<endl;
return 0;
}
/*
********
************
####....#.
#..###.....##....
###.......###### ### ###
........... #...# #...#
##*####### #.#.# #.#.#
####*******###### #.#.# #.#.#
...#***.****.*###.... #...# #...#
....**********##..... ### ###
....**** *****....
#### ####
###### ######
##############################################################
#...#......#.##...#......#.##...#......#.##------------------#
###########################################------------------#
#..#....#....##..#....#....##..#....#....#####################
########################################## #----------#
#.....#......##.....#......##.....#......# #----------#
########################################## #----------#
#.#..#....#..##.#..#....#..##.#..#....#..# #----------#
########################################## ############
*/