1308 高精除 1308【例1.5】高精除 信息学奥赛一本通
在线测评地址http://ybt.ssoier.cn:8088/index.php
//准备用8位压位,高效算法思路如下
/*
10000/89=112......32
2^0*89=89
2^1*89=178
2^2*89=356
2^3*89=712
2^4*89=1424
2^5*89=2848
2^6*89=5696
ans=0
10000-5696=4304, ans+=2^6, ans=64
4304-2848=1456, ans+=2^5, ans=96
1456-1424=32, ans+=2^4, ans=112
*/
//编了很长时间,大约3个小时吧,压位比较烧脑。但程序效率高。
//样例通过,提交AC.2019-10-25 21:04
#include <stdio.h>
#include <string.h>
#define maxn 320
#define base 100000000
#define bit 8
char s[maxn];
int a[maxn/bit],b[maxn/bit],c[1000][maxn/bit],d[1000][maxn/bit],ans[maxn/bit];
void read(int *f){
int i,len,tmp;
char t;
scanf("%s",s+1);
len=strlen(s+1);
for(i=1;i<=len/2;i++)
t=s[i],s[i]=s[len-i+1],s[len-i+1]=t;
f[0]=(len-1)/bit+1;
for(i=1;i<=len;i++){//编写该处转换,折腾了很长时间
if((i-1)%bit==0)f[(i-1)/bit+1]=0,tmp=1;
f[(i-1)/bit+1]+=(s[i]-'0')*tmp;
tmp*=10;
}
}
void print(int *f){
int i;
printf("%d",f[f[0]]);
for(i=f[0]-1;i>=1;i--)printf("%08d",f[i]);
printf("\n");
}
int cmp(int *x,int *y){//x>y 1;x<y -1;x==y 0;
int i;
if(x[0]>y[0])return 1;
if(x[0]<y[0])return -1;
for(i=x[0];i>=1;i--)
if(x[i]>y[i])return 1;
else if(x[i]<y[i])return -1;
return 0;
}
void multo(int *x,int *y,int v){//x=y*v
int i;
x[1]=0;
for(i=1;i<=y[0];i++)x[i]+=y[i]*v,x[i+1]=x[i]/base,x[i]%=base;
if(x[i])x[0]=i;
else x[0]=y[0];
}
void add(int *x,int *y){//x+=y
int i;
x[0]=x[0]>y[0]?x[0]:y[0];
for(i=1;i<=x[0];i++)x[i]+=y[i],x[i+1]+=x[i]/base,x[i]%=base;
if(x[i])x[0]=i;
}
void dec(int *x,int *y){//x-=y x>=y
int i;
for(i=1;i<=x[0];i++){
x[i]-=y[i];
if(x[i]<0)x[i+1]-=1,x[i]+=base;
}
while(x[i]==0)i--;
x[0]=i;
}
void solve(){
int i,mx;
memcpy(c[0],b,sizeof(b)),d[0][0]=1,d[0][1]=1,i=1;
for(i=0;cmp(a,c[i])>=0;i++){
multo(c[i+1],c[i],2);
multo(d[i+1],d[i],2);
}
mx=i-1,ans[0]=1,ans[1]=0;
for(i=mx;i>=0;i--){
if(cmp(a,c[i])>=0){
dec(a,c[i]);
add(ans,d[i]);
}
}
print(ans);//商
print(a);//余数
}
int main(){
read(a);
read(b);
solve();
return 0;
}