1308 高精除 1308【例1.5】高精除 信息学奥赛一本通

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;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值