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

来源:互联网 发布:学软件好找工作吗 编辑:程序博客网 时间:2024/04/29 21:57

麦森数 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 1099511627776LLusing 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]);    }}
0 0
原创粉丝点击