zoukankan      html  css  js  c++  java
  • 【高精度】麦森数 NOIP 2003

    [NOIP2003]麦森数

    时间限制: 1 Sec  内存限制:64 MB

    题目描述

    形如2^p-1的素数称为麦森数,这时p一定也是个素数。但反过来不一定,即如果p是个素数,2^p-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是p=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。现要求输入p(1000< P < 3100000),计算2^p-1的位数和最后500位数字(用十进制高精度数表示)。

    输入

    第1行:1个整数p(1000

    输出

    第1行:十进制高精度数2^p-1的位数;第2..11行:十进制高精度数2^p-1的最后500位数字(每行输出50位,共输出10行,不足500位时高位补0); 注意:不必验证2^p-1与p是否为素数。

    样例输入

    (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

    1279

    样例输出

    386
    00000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000
    00000000000000104079321946643990819252403273640855
    38615262247266704805319112350403608059673360298012
    23944173232418484242161395428100779138356624832346
    49081399066056773207629241295093892203457731833496
    61583550472959420547689811211693677147548478866962
    50138443826029173234888531116082853841658502825560
    46662248318909188018470682222031405210266984354887
    32958028878050869736186900714720710555703168729087 
    

    刚开始看到这么一大堆(tuÓ)输出,其实我是拒绝的。

    想了想,第一,高精度;第二,求p次幂要用快速幂(了解快速幂详见点这里!!)。

    一、首先我们要知道怎么存500位的数,那么就存在一个结构体数组里面,进行高精度乘法的时候,就可以想一想竖式是怎么计算的。但是想一想竖式是从最低位开始乘起来的,所以我用的数组是倒序存数,最后输出只要倒回来输出就行了。

    这里用到了重载运算符:

    big operator *(big &ys)const
    	{big ans;
    		
    		for(int i=1;i<=len;i++)
    			for(int j=1;j<=ys.len;j++)
    			{
    				if(i+j-1>500) break;//如果位数>500,不用考虑
    				ans.A[i+j-1]+=A[i]*ys.A[j];//为什么是i+j-1,
                                                               //自己想想竖式计算
                                    if(ans.A[i+j-1]>=10)//向后进位
    				{
    					ans.A[i+j]+=ans.A[i+j-1]/10;
    					ans.A[i+j-1]%=10;
    				}
    			}
    		for(int i=500;i>=1;i--)//求位数
                            if(ans.A[i]!=0){ans.len=i;break;}
                    return ans;
    	}

    二、进行幂运算的时候,要把p进行二进制划分(自己看上面的链接)。

    三、代码如下:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    
    int p;
    
    struct big
    {
    	int A[501],len;//A存数,len存位数
    	big(){memset(A,0,sizeof A);len=0;}//清0
    	big operator *(big &ys)const//重载乘号
    	{big ans;
    		
    		for(int i=1;i<=len;i++)
    			for(int j=1;j<=ys.len;j++)
    			{
    				if(i+j-1>500) break;
    				ans.A[i+j-1]+=A[i]*ys.A[j];
    				if(ans.A[i+j-1]>=10)
    				{
    					ans.A[i+j]+=ans.A[i+j-1]/10;
    					ans.A[i+j-1]%=10;
    				}
    			}
    		for(int i=500;i>=1;i--)
    			if(ans.A[i]!=0){ans.len=i;break;}
    		return ans;
    	}
    }danwei,ans;
    
    
    int main()
    {
    	scanf("%d",&p);
    	danwei.A[1]=2;danwei.len=1;//danwei即使底数
    	ans.A[1]=1;ans.len=1;
    	printf("%d
    ",int(p*log10(2))+1);
    	while(p)//快速幂
    	{
    		if(p&1) ans=ans*danwei;
    		p/=2;
    		danwei=danwei*danwei;
    	}
    	ans.A[1]--;//求的是2^p-1,所以最后--
    	for(int i=1;i<=10;i++)
    	{
    		for(int j=1;j<=50;j++)
    			printf("%d",ans.A[501-(i-1)*50-j]);//倒序输出
    		printf("
    ");
    	}
    	
    }
  • 相关阅读:
    GCD 使用说明
    iOS操作系统的层次结构
    Objective-C 类型转换
    UIView和Masonry实现动画效果
    iOS 常用手势
    SDUT 2610 Boring Counting(离散化+主席树区间内的区间求和)
    HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)
    NBUT 1525 Cow Xor(01字典树+前缀思想)
    HDU 4825 Xor Sum(经典01字典树+贪心)
    HDU 1069 Monkey and Banana(二维偏序LIS的应用)
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039526.html
Copyright © 2011-2022 走看看