【codevs1087&&NOIP2003】麦森数,高精度+对数+快速幂

麦森数 2003年NOIP全国联赛普及组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。

任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)

输入描述 Input Description
文件中只包含一个整数P(1000<P<3100000)

输出描述 Output Description
第一行:十进制高精度数2P-1的位数。
第2-11行:十进制高精度数2P-1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)
不必验证2P-1与P是否为素数。
样例输入 Sample Input
1279

样例输出 Sample Output
386

00000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000

00000000000000104079321946643990819252403273640855

38615262247266704805319112350403608059673360298012

23944173232418484242161395428100779138356624832346

49081399066056773207629241295093892203457731833496

61583550472959420547689811211693677147548478866962

50138443826029173234888531116082853841658502825560

46662248318909188018470682222031405210266984354887

32958028878050869736186900714720710555703168729087
写来前面:好久以前写的,今天发一下,不得不说过去的题目质量真高……
———————————————————————
———————————————————————
思路
同标题,注意判断位数时用到log函数,即2^p-1的位数等于p/log2(10)+1,证明如下:
对于2^p-1,它的位数等于2^p(因为2的正整数次幂个位只有2,4,8,6,则减1不影响位数),2^p的位数等于lg(2^p)取整后+1(这个可以自己写写看),则
log10(2^p)=log2(2^p)/log2(10)=p/log2(10);

当时的我还不会快速幂,所以用了一个比较卡数据的方法,用2^30,2^20,2^10,2分别进行高精乘单精,最后
过了……
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define maxn 1099511627776LL
using namespace std;
long long a[1000000];
int n;
void add(long long x)
{
    long long jw=0;
    for (int i=1;i<=min(a[0],501LL);i++)
    {
        a[i]=x*a[i]+jw;
        jw=0;
        if (a[i]>=10)
        jw+=(a[i]/10),a[i]%=10;
    }
    if (jw>0) a[++a[0]]=jw;
    while (a[a[0]]>=10&&a[0]<=501) 
    a[a[0]+1]=a[a[0]]/10,
    a[a[0]++]%=10;
    a[501]=0;
    a[0]=min(a[0],501LL);
}
main()
{
    a[1]=1;
    a[0]=1;
    scanf("%d",&n);
    for (int i=1;i<=n/40;i++)
    add(maxn);
    for (int i=1;i<=(n-(n/40)*40)/20;i++)
    add(1048576);
    for (int i=1;i<=(n-20*(n/20))/10;i++)
    add(1024);
    for (int i=1;i<=n-10*(n/10);i++)
    add(2);
    double k=log10(2);
    printf("%d",int(n*k+1));
    a[1]--;
    for (int i=500;i>=1;i--)
    {
        if (i%50==0) printf("\n");
        printf("%d",a[i]);
    }
}

你可能感兴趣的:(【codevs1087&&NOIP2003】麦森数,高精度+对数+快速幂)