码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷OJ P1045 麦森数 解题报告

时间:2015-05-21 01:18:41      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

洛谷OJ P1045 麦森数 解题报告

by MedalPluS

  题目描述

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

  输入描述

  文件中只包含一个整数P(1000<P<3100000)

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

  分析

  首先2p-1的位数可以通过换底公式得到,即log102p+1 通过换底公式可以转换为log2/log10*p+1

  然后就是高精度的过程

  但注意,直接模拟的话会TLE,想一想为什么?因为直接模拟的复杂度应为500*500*3100000简直就是天文数字。。

  那么怎么优化呢?

  1.FFT优化高精度乘法,即降至500*8*3100000还是有TLE的风险

  2.快速幂优化求幂,即降至500*8*19完全可以无压力AC

  加上FFT代码太长,这里不贴了。。但不过只用快速幂是可以AC的

  代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 const int maxn=50001;
 7 
 8 //求2^p-1 高精度乘法&高-单 &快速幂 
 9 
10 int ans[maxn],a[maxn],p;
11 int test1[maxn],test2[maxn];
12 int c[maxn];
13 
14 void mult(int a[],int b[]){
15     int len,i,j,tmp,k=0;
16     memset(c,0,sizeof(c));
17     for(i=1;i<=a[0];i++){
18       for(j=1;j<=b[0];j++)
19       {
20           tmp=a[i]*b[j]+k;
21           c[i+j-1]+=tmp%10;
22           k=tmp/10+c[i+j-1]/10;
23           c[i+j-1]%=10;
24       }
25       len=i+j-2;
26       while(k!=0)
27       {
28         c[++len]+=k%10;
29         k=k/10+c[len]/10;
30         c[len]%=10;
31       }
32     }
33     c[0]=min(len,500);
34     for(i=500;i>=0;i--)
35       a[i]=c[i];
36 }
37 
38 void qmult(){
39     ans[ans[0]=1]=1;
40     a[a[0]=1]=2;
41     while(p){
42         if(p&1)mult(ans,a);
43         p>>=1;
44         mult(a,a);
45     }
46 }
47 
48 void dele(){
49     int i=1;
50     while(1){
51         if(ans[i]-1>=0)
52         {
53           ans[i]--;
54           break;
55         }
56         ans[i]=(ans[i]+9)%9;
57         i++;
58     }
59 }
60 
61 void out(){
62     int i,t=0;
63     for(i=500;i>=1;i--){
64         cout<<ans[i];
65         t++;
66         if(t%50==0)cout<<endl;
67     }
68 }
69 
70 int main(){
71     scanf("%d",&p);
72     cout<<(int)(log(2)/log(10)*p+1)<<endl;
73     qmult();
74     dele();
75     out();
76     return 0;
77 }

 

 

 

洛谷OJ P1045 麦森数 解题报告

标签:

原文地址:http://www.cnblogs.com/maopengsen/p/4518626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!