麦森数(分治或快速幂)
Posted thunder-110
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了麦森数(分治或快速幂)相关的知识,希望对你有一定的参考价值。
题目分析:
第一问是很简单的,只需要求一个对数而已,数学原理:十进制正整数n的位数为int(log10(n))+1。所以2^P-1的位数int(log10(2)*p)+1 。
2^p = 10^(p*log10(2) ) , 所以2^p的位数是p*log10(2)。
第二问的关键是高精度乘法和指数幂的运算,而且由于题目要求最后500位数字,所以在计算乘法的时候我们只要求计算乘数的低500位就好了。
指数幂的运算不能硬乘,而要采用分治算法,否则就超时了。分治递归算法求指数幂是非常经典的,其数学原理是a^n = a^(n/2)*a^(n/2)*f(a),其中f(a) = 1(n%2==0)或f(a) = a(n%2==1)。
另外我们也可以创建一个栈,记录每次执行(n /= 2)前n的值是奇数还是偶数,然后根据上面的数学原理,模仿递归的思路,从n=1或n=0开始逆向计算a^n。
采用递归算法的时候,由于存储高精度整数数组的大小是预置MAX = 1000,所以在调用递归函数的时候要按引用传递参数,否则到了后面空间就不够分配了。
为了满足“每行输出50位”的条件,我把存储高精度整数数组的元素设置成5位数,这样输出的时候只需每行输出10个元素就行了。
1 #include<iostream> 2 #include<cstdio> 3 #include <cctype> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<string> 8 #include<cmath> 9 #include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const int INF= 0x3f3f3f3f; 20 const int N=1e6+5; 21 22 int p,a[505],b[1005]; 23 24 void quick(int x) 25 { 26 if(x==0) return; 27 quick(x/2); 28 mem(b,0); 29 for(int i=0;i<500;i++) 30 { 31 for(int j=0;j<500;j++) 32 { 33 if(x&1) b[i+j] += a[i]*a[j]*2; 34 else b[i+j] += a[i]*a[j]; 35 } 36 } 37 for(int i=0;i<500;i++) 38 { 39 a[i] = b[i]%10; 40 b[i+1]+= b[i]/10; 41 } 42 } 43 44 int main() 45 { 46 cin>>p; 47 a[0]=1; 48 quick(p); 49 50 a[0]--; 51 int k=0; 52 while(a[k]<0) a[k+1]--,a[k]+=10,k++; 53 54 cout<< floor( p*log10(2)+1 )<<endl; 55 for(int i=499;i>=0;i--) 56 { 57 cout<<a[i]; 58 if((i)%50==0) cout<<endl; 59 } 60 }
以上是关于麦森数(分治或快速幂)的主要内容,如果未能解决你的问题,请参考以下文章