006.高精度快速幂
P1045 [NOIP 2003 普及组] 麦森数
题目描述
形如 \(2^{P}-1\) 的素数称为麦森数,这时 \(P\) 一定也是个素数。但反过来不一定,即如果 \(P\) 是个素数,\(2^{P}-1\) 不一定也是素数。到 1998 年底,人们已找到了 37 个麦森数。最大的一个是 \(P=3021377\),它有 909526 位。麦森数有许多重要应用,它与完全数密切相关。
任务:输入 \(P(1000<P<3100000)\),计算 \(2^{P}-1\) 的位数和最后 \(500\) 位数字(用十进制高精度数表示)
输入格式
文件中只包含一个整数 \(P(1000<P<3100000)\)
输出格式
第一行:十进制高精度数 \(2^{P}-1\) 的位数。
第 \(2\sim 11\) 行:十进制高精度数 \(2^{P}-1\) 的最后 \(500\) 位数字。(每行输出 \(50\) 位,共输出 \(10\) 行,不足 \(500\) 位时高位补 \(0\))
不必验证 \(2^{P}-1\) 与 \(P\) 是否为素数。
输入输出样例 #1
输入 #1
1279
输出 #1
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
说明/提示
【题目来源】
NOIP 2003 普及组第四题
思路
数学方法计算位数
位数=p*log10(2)+1
int p;
read(p);
int len=p*log10(2)+1;
wr2(len);
//设置位数
SIZE=max(500,len)+5;
乘法只处理后500位
void BigMulBig(int a[],int b[],int c[]){
memset(c,0,sizeof(int)*SIZE);
for(int i=1;i<=a[0]&&i<=500;++i){//超过500的不处理
int ex=0;
for(int j=1;j<=b[0]&&i+j-1<=500;++j){//超过500的不处理
c[i+j-1]=c[i+j-1]+a[i]*b[j]+ex;
ex=c[i+j-1]/10;
c[i+j-1]%=10;
}
int k=i+b[0];
while(ex&&k<=500){//超过500的不处理
c[k]+=ex;
ex=c[k]/10;
c[k]%=10;
k++;
}
}
int n=a[0]+b[0];
while(c[n]==0&&n>1)n--;
c[0]=n;
}
快速幂计算2^p
//初始化 a 为 1
// a[SIZE]= {0} , a[0]=a[1]=1;
void qp(int a[],int p){
int b[SIZE],temp[SIZE];
b[0]=1,b[1]=2;
while(p){
if(p&1){
BigMulBig(a,b,temp);
memcpy(a,temp,sizeof(temp));
}
BigMulBig(b,b,temp);
memcpy(b,temp,sizeof(temp));
p>>=1;
}
}
//得到 a = 2^p
减一 ( 比较丑陋 )
//偷懒直接用模板
// b[SIZE]={0},b[0]=b[1]=1
void BigSub2(int a[],int b[]){
int i=1;
while(i<=b[0]){
if(a[i]<b[i]){
int j=i+1;
while(j<=a[0]&&a[j]==0)a[j++]=9;
a[j]--;
a[i]+=10;
}
a[i]-=b[i];
i++;
}
while(i<=a[0]&&a[i]<0){
a[i]+=10;
a[i+1]--;
i++;
}
while(a[0]>1&&a[a[0]]==0)a[0]--;
}
//得到 a-1
code
#include<bits/stdc++.h>
using namespace std;
namespace IO{template<typename type>inline void read(type &x){x=0;int f=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}f?x=-x:0;}template<typename type>inline void wr(type x){x<0?x=-x,putchar('-'):0;static short stk[50],top(0);do stk[++top]=x%10,x/=10;while(x);while(top)putchar(stk[top--]+'0');}template<typename type>inline void wr1(type x){wr(x),putchar(' ');}template<typename type>inline void wr2(type x){wr(x),putchar('\n');}inline void readline(char *s){char ch=getchar();int i(0);while(ch=='\n'||ch=='\r')ch=getchar();while(ch!='\n'&&ch!='\r'&&ch!=EOF)s[i++]=ch,ch=getchar();s[i]='\0';}inline void write(const char*s){while(*s)putchar(*s++);}inline void writeline(const char*s){write(s),putchar('\n');}}using namespace IO;
int SIZE;//待定
void BigRead(int a[]){char s[SIZE];scanf("%s",s);int n=strlen(s);memset(a,0,sizeof(int)*SIZE);a[0]=n;for(int i=n;i;--i)a[i]=s[n-i]-'0';}
void BigWrite(int a[]){for(int i=a[0];i;i--)putchar(a[i]+'0');}
void BigSub2(int a[],int b[]){int i=1;while(i<=b[0]){if(a[i]<b[i]){int j=i+1;while(j<=a[0]&&a[j]==0)a[j++]=9;a[j]--;a[i]+=10;}a[i]-=b[i];i++;}while (i<=a[0]&&a[i]<0){a[i]+=10;a[i+1]--;i++;}while(a[0]>1&&a[a[0]]==0)a[0]--;}
void BigMulBig(int a[],int b[],int c[]){
memset(c,0,sizeof(int)*SIZE);
for(int i=1;i<=a[0]&&i<=500;++i){
int ex=0;
for(int j=1;j<=b[0]&&i+j-1<=500;++j){
c[i+j-1]=c[i+j-1]+a[i]*b[j]+ex;
ex=c[i+j-1]/10;
c[i+j-1]%=10;
}
int k=i+b[0];
while(ex&&k<=500){
c[k]+=ex;
ex=c[k]/10;
c[k]%=10;
k++;
}
}
int n=a[0]+b[0];
while(c[n]==0&&n>1)n--;
c[0]=n;
}
void qp(int a[],int p){
int b[SIZE],temp[SIZE];
b[0]=1,b[1]=2;
while(p){
if(p&1){
BigMulBig(a,b,temp);
memcpy(a,temp,sizeof(temp));
}
BigMulBig(b,b,temp);
memcpy(b,temp,sizeof(temp));
p>>=1;
}
}
int main(){
int p;read(p);
int len=p*log10(2)+1;
wr2(len);
SIZE=max(500,len)+5;
int a[SIZE]={0};
a[0]=a[1]=1;
qp(a,p);
int b[SIZE]={0};
b[0]=b[1]=1;
BigSub2(a,b);
int t=500;
for(int i=0;i<10;++i){
for(int j=0;j<50;++j){
wr(a[t--]);
}
putchar('\n');
}
}
I am the bone of my sword

浙公网安备 33010602011771号