NOIP2003 普及组 洛谷P1045 麦森数 (快速幂+高精度)
有两个问题:求位数和求后500位的数。
求位数:最后减去1对答案的位数是不影响的,就是求2p的位数,直接有公式log10(2)*p+1;
求后500位的数:容易想到快速幂和高精度;
1 #include2 using namespace std; 3 int p,f[1001],/*基数*/res[1001],/*记录答案*/sav[1001]/*中间数组*/; 4 5 void work_1(){//记录答案 6 memset(sav,0,sizeof(sav));//中间数组每次用时初始化为0 7 for(int i=1;i<=500;i++)//最后500位 8 for(int j=1;j<=500;j++)//两层循环:高精乘法的精髓 9 sav[i+j-1]+=res[i]*f[j];//先计算每一位上的值(不进位) 10 for(int i=1;i<=500;i++){//处理进位 11 sav[i+1]+=sav[i]/10; 12 sav[i]%=10; 13 } 14 memcpy(res,sav,sizeof(res));//把sav的值赋给res 15 } 16 17 void work_2(){//基数相乘 18 memset(sav,0,sizeof(sav)); 19 for(int i=1;i<=500;i++) 20 for(int j=1;j<=500;j++) 21 sav[i+j-1]+=f[i]*f[j]; 22 for(int i=1;i<=500;i++){ 23 sav[i+1]+=sav[i]/10; 24 sav[i]%=10; 25 } 26 memcpy(f,sav,sizeof(f)); 27 } 28 29 int main(){ 30 scanf("%d",&p); 31 printf("%d\n",(int)(log10(2)*p+1));//求位数 32 res[1]=1;f[1]=2;//高精度赋初值 33 while(p){//快速幂模板 34 if(p&1) work_1(); 35 work_2();//基数相乘 36 p>>=1; 37 } 38 res[1]-=1;//最后要减1 39 for(int i=500;i>=1;i--){ 40 if(i!=500 && i%50==0) cout< //每50个数要换行 41 else cout<<res[i]; 42 } 43 return 0; 44 }