FNOI_TEST_1 b(高精度除法)

http://www.elijahqi.win/archives/597
2.整除(b.cpp/c/pas)
【问题描述】 给出两个正整数 n、m,求 n 除以 m 的商和余数。 【输入数据】 第一行一个正整数 n。 第二行一个正整数 m。 【输出数据】 第一行一个正整数表示 n 除以 m 的商。 第二行一个正整数表示 n 除以 m 的余数。 【输入输出样例 1】 b.in b.out 97 15 6 7 【输入输出样例 2】 b.in b.out 919308219 1254 733100 819 【输入输出样例 3】 b.in b.out 37016651297381047164 7 5288093042483006737 5 【输入输出样例 4】 b.in b.out 666666666666666666666666666666 233 2861230329041487839771101573 157 【数据规模和约定】 测试点编号 n m 1 <=100 <=9 2 <=10^7 <=1000 3 <=10^9 <=10000 4 <=10^100 <=9 5 <=1000 6 <=10^50 7 <=10^10000 <=9 8 <=1000 9 <=10^50 10 <=10^200 对于 100%的数据:1<=n<=10^10000,1<=m<=10^200,m<=n

大意就是求两个大整数相除 注意存在余数为0的情况

#include<cstdio>
#include<cstring>
#define N 11000
#define N1 220
int ans[N];
char n1[N],m1[N1];
int n[N],m[N1],nn,mm,ans1,cnt,st=1;
inline void subtract(int st1,int ed){
    int tmp=0;
    for (int i=1;i<=mm;++i){
        n[ed-i+1]+=tmp;
        if (n[ed-i+1]<m[mm-i+1]) tmp=-1,n[ed-i+1]+=10;else tmp=0;
        n[ed-i+1]-=m[mm-i+1];
    }
    if (ed-st1+1>mm) n[st1]+=tmp;
    while (n[st]==0) st++;

}
inline bool judge(int st1,int ed){
    int ll=ed-st1+1; if (ll>mm) return true;else if(ll<mm) return false;
    for (int i=1;i<=mm;++i) {
        if(n[st1+i-1]<m[i]) return false;
        if(n[st1+i-1]>m[i]) return true;
    }

}
int main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%s",n1+1);
    scanf("%s",m1+1);
    nn=strlen(n1+1);mm=strlen(m1+1);
    for (int i=1;i<=nn;++i) n[i]=n1[i]-'0';
    for (int i=1;i<=mm;++i) m[i]=m1[i]-'0';
    //for (int i=1;i<=nn;++i) printf("%d",n[i]);printf("\n");
    //for (int i=1;i<=mm;++i) printf("%d",m[i]);printf("\n");
    for (int i=mm;i<=nn;++i){
        ans1=0;
        while (judge(st,i)){
            ans1++;
            subtract(st,i);
            //for (int i=1;i<=nn;++i) printf("%d",n[i]);printf("\n");
        //  for (int i=1;i<=mm;++i) printf("%d",m[i]);printf("\n");
        }
        ans[++cnt]=ans1;

    }
    int num=1;while (ans[num]==0) num++;
    for (int i=num;i<=cnt;++i) printf("%d",ans[i]);printf("\n");
    if(st>nn) printf("0\n");
    for (int i=st;i<=nn;++i) printf("%d",n[i]);

    return 0;
}

一起看下官方题解吧

2.整除(b) 【30 分】 把 n 和 m 作为 int 读入,直接计算答案。时间复杂度 O(1)。 【70 分】 m<=10000,考虑从高位到低位逐位确定商,模拟竖式除法,每一位都做一个 int 以内的除法,求出商以后自然得到余数。设 len1 为 n 的位数, len2 为 m 的位数, 时间复杂度 O(len1)。 【80 分】 同样考虑从高位到低位逐位确定商,模拟竖式除法,但由于 m 超过了 longlong, 无法直接做除法。由于商的每一位都<=9,用减法模拟除法即可。实现比较两个 高精度数的大小和高精度减法即可。由于比大小时 n 的位数为 O(len1),故时间 复杂度 O(9*len1^2),无法通过 9、10 测试点。 【100 分】 注意到减法模拟除法时 n 的前面很多位都是 0,事实上只会涉及到当前的 n 的后 len2+1位,故比大小和高精度减法复杂度均为O(len2),时间复杂度O(9*len1*len2)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值