麦森数(洛谷-P1045)

题目描述

形如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;	
}

/*
                ********
               ************
               ####....#.
             #..###.....##....
             ###.......######              ###            ###
                ...........               #...#          #...#
               ##*#######                 #.#.#          #.#.#
            ####*******######             #.#.#          #.#.#
           ...#***.****.*###....          #...#          #...#
           ....**********##.....           ###            ###
           ....****    *****....
             ####        ####
           ######        ######
##############################################################
#...#......#.##...#......#.##...#......#.##------------------#
###########################################------------------#
#..#....#....##..#....#....##..#....#....#####################
##########################################    #----------#
#.....#......##.....#......##.....#......#    #----------#
##########################################    #----------#
#.#..#....#..##.#..#....#..##.#..#....#..#    #----------#
##########################################    ############
*/



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃货智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值