首先要求2p-1的结果有多少位,因为减一并不会影响其的位数,所以只要求2p有多少位就可以了,直接看图。
重点是怎么求2p-1的结果的后500位
高精度
首先需要了解一下快速幂的原理,这里就不说了,直接上代码
long long Mode(long long a,long long b) { long long sum=1; a=a%m; while(b>0) { if(b%2==1) sum=(sum*a)%m;//修改 b/=2; a=(a*a)%m;//修改 } return sum; }
高精度的话我们只需要对上述修改的地方做一个大数的处理就可以了
高精度的思路
对每个位置上的数单独计算不进位,最后处理的时候统一进位
void calculute1() { memset(sav,0,sizeof(sav));//将sav数组全部赋为0 for(int i=1;i<=500;i++) for(int j=1;j<=500;j++)//每一位单独计算 sav[i+j-1]+=res[i]*f[j]; for(int i=1;i<=500;i++)//进位处理 { sav[i+1]+=sav[i]/10;//满10进1 sav[i]%=10;//进位后剩下的部分 } memcpy(res,sav,sizeof(res));//将sav数组复制到res数组中去 }
这里取一个33*44作为例子对上述代码的过程进行说明
快速幂的还有一个部分的原理和上面一个是相同的
void calculute2() { memset(sav,0,sizeof(sav)); for(int i=1;i<=500;i++) for(int j=1;j<=500;j++) sav[i+j-1]+=f[i]*f[j]; for(int i=1;i<=500;i++) { sav[i+1]+=sav[i]/10; sav[i]%=10; } memcpy(f,sav,sizeof(f)); }
完整代码
#include <iostream> #include<cmath> #include<cstring> using namespace std; int sav[1001],p,f[1001],res[1001]; void calculute1() { memset(sav,0,sizeof(sav)); for(int i=1;i<=500;i++) for(int j=1;j<=500;j++) sav[i+j-1]+=res[i]*f[j]; for(int i=1;i<=500;i++) { sav[i+1]+=sav[i]/10; sav[i]%=10; } memcpy(res,sav,sizeof(res)); } void calculute2() { memset(sav,0,sizeof(sav)); for(int i=1;i<=500;i++) for(int j=1;j<=500;j++) sav[i+j-1]+=f[i]*f[j]; for(int i=1;i<=500;i++) { sav[i+1]+=sav[i]/10; sav[i]%=10; } memcpy(f,sav,sizeof(f)); } int main() { int p,num; cin>>p; num=log10(2)*p+1; cout<<num<<endl; res[1]=1; f[1]=2; while(p!=0) { if(p%2==1) calculute1(); p/=2; calculute2(); } res[1]--; for(int i=500;i>=1;i--) { if(i!=500&&i%50==0) cout<<endl; cout<<res[i]; } return 0; }