百练 2706 麦森数

/*
这道题过得好艰难啊
一直TLE
后来看到大神们都用位运算什么的
敬仰之心顿生。。。 
之前直接模拟大数乘法
导致输入3021377时很久跳不出来
后来把2的指数mod10算,结果还是不行
最后就采用了下面的方法
很巧妙
能大大减少循环次数
输入3021377一瞬间就出来了
提交后status上显示0ms
算法才是王道啊 
*/
#define LOCAL
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 126
using namespace std;
void mutiply(int a[N],int b[N])
{
       int i,j,c[N]={0};
       for(i=0;i<N;i++)
       {
              for(j=0;j<N;j++)                
              {
                 if(i+j<N)   //这里加个判断条件一是不需要算超过500位的二是会提示内存读取错误 
                    c[j+i]+=a[j]*b[i];                           
              }
              for(j=0;j<N-1;j++)
              {
                     if(c[j]>=10000)
                     {
                           c[j+1]+=c[j]/10000;
                           c[j]%=10000;            
                     }                  
              }
       }     
       memcpy(a,c,N*sizeof(int));
}
int main()
{
#ifdef LOCAL
       freopen("input.txt","r",stdin);
       freopen("output.txt","w",stdout);
#endif

    
    int n,p,i,ans[N]={1},two[N]={2};
    cin>>p;n=p;
    while(p)
    {
           if(p&1)        //当p的第一位为1时才乘否则直接跳过 
             mutiply(ans,two);
           mutiply(two,two);//这里是求2^(2^(i+1))
           p=p>>1;        
    }
    ans[0]--;
    cout<<(int)(log10(2.0)*n+1)<<endl;//用公式求 
    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;
}

你可能感兴趣的:(百练 2706 麦森数)