NOIP2003 普及组 洛谷P1045 麦森数 (快速幂+高精度)


有两个问题:求位数和求后500位的数。

求位数:最后减去1对答案的位数是不影响的,就是求2p的位数,直接有公式log10(2)*p+1;

求后500位的数:容易想到快速幂和高精度;

 1 #include
 2 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 }