麦森数

题目大意:计算2^P-1的位数和它的最后500位并输出。
1、计算位数:2^P-1的位数为[log10(2^P)]+1==[Plog10(2)]+1
2、计算最后500位:高精度预处理2^i,计算时将P分解成二进制形式,然后相乘,只保留500位

代码一:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#define N 126
using namespace std;
int ans[N],anspow[N];
void mult(int ans[],int anspow[])
{
  int i,j;
  int c[N];
  memset(c,0,sizeof(c));
        for(i=0;i<N;i++)  
        {  
            for(j=0;j<N;j++)                  
            {  
                if(i+j<N)//超出500位的部分不计算
                {
                  c[i+j]+=ans[j]*anspow[i]; 
                }                              
            }  
           for(j=0;j<N-1;j++)  
           {  
                if(c[j]>=10000) 
                {  
                    c[j+1]+=c[j]/10000;//压4位  
                     c[j]%=10000;              
                }                    
           }  
        }  
        memcpy(ans,c,N*sizeof(int));  //复制函数
}
int main()
{
  int P,i,j;
  while(cin>>P)
  {
    memset(ans,0,sizeof(ans));
    memset(anspow,0,sizeof(anspow));
    printf("%d\n",(int)(P*log10(2)+1));
    ans[0]=1;
    anspow[0]=2;
/************关键部分计算2^P*******
 2^p=(2^1)*(2^2)*(2^3)*(2^4)*(2^5)………………
 简单说下:P=5 -----101(二进制)
    p & 1 =1(最右边一位) -->>>ans=2 anspow=2
    p>>1=110  anspow=2^2
    p & 1 =0  此时表明2^3不存在 ans=2 anspow=2^4
    p>>1=1       
    p & 1 =1  ------>>>>> ans=2^5 
    p>>1=0   ------结束    
************************************/
    while(P)
    {
        if( P & 1)
            mult(ans,anspow);
        P>>=1;
            mult(anspow,anspow);
    }
    ans[0]--;//2^P的个位为2,4,6,8,故可以-1
/****************输出格式的控制************************/
    for(i=124;i>=0;i--)
    {
        if(i%25==12)  
        {
           printf("%02d\n%02d",ans[i]/100,ans[i]%100);  
        }
        else  
        {  
           printf("%04d",ans[i]);
           if(i%25==0) printf("\n");
        }     
    }
/***************************************************/
  }
return 0;
}

代码二:

/*************麦森数****************/
#include<iostream>
#include<cstdio>
#include<cmath>
#define N 100   //压5位
using namespace std;
int ans[N];
void  mult(int t)
{
  int i,temp,last=0;
      for ( i=N-1; i>=0; i--)
    { 
        temp=(ans[i]<<t)+last;   //乘2^t,加进位 
        last=temp/100000; 
        ans[i]=temp-last*100000;  //temp%100000 
    } 
}
void output()
{
   int i;
   for(i=1;i<=N;i++)
   {     printf("%05d",ans[i-1]);
        if (i%10==0)cout<<endl;   
   } 
}
int main()
{
  int P,times;
  while(cin>>P)
  {
      memset(ans,0,sizeof(ans));
      ans[N-1]=1;
      cout<<(int)(P*log10(2)+1)<<endl;
/***********************关键部分*****************
  2^P=2^(14*times)*2^(P%14) 用移位
  之所以取14的原因 2^14*(99999)=1.638382*10^9 在(int)
  范围,15以后都会超int,主要体现在mult()中      
 **********************************************/
      times=P/14;  //只能到14 15以后压缩时会超范围
      while(times--)
          mult(14);
       mult(P%14);
       --ans[99];
      output();
  }
return 0;
}

转自:http://www.cnblogs.com/lsx54321/archive/2012/07/25/2608414.html

点赞