hdu 6646 A + B = C 大数思维

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6653

题意:

给你数字 a , b , c , a,b,c, abc, 要你找出随意的一个 x , y , z x,y,z xyz 使得 a ∗ 1 0 x + b ∗ 1 0 y = c ∗ 1 0 z a*10^{x}+b*10^{y}=c*10^{z} a10x+b10y=c10z 成立。

做法:

我们考虑c这个数的最高位的来源,c这个数的最高位有两种可能的来源。第一种是a或者b的最高位直接相加(包括a或b的这一位是0的情况)而来,另外一种是a和b的最高位进行相加通过进位而来。

所以我们可以枚举 a a a b b b 两个数字的最高位在c的最高位次高位是否能满足条件即可。这里还用到了一个优化(如果c的第一位不是1的话,就排除了a和b相加进位的情况)。

赛上的时候因为用了stl的string的各种操作,疯狂T怎么样都T、T到绝望。赛后用了char写写就243ms,我哭了…果然我还是太菜了… 附上一堆测试数据供博友自行检查。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define ll long long
using namespace std;
const int maxn=100009;
int flag,ctc,len[4],x,y,z;
char S[3][maxn];
char a[maxn],c[maxn];
int deal(int idc,int ida,int st){
    if(flag) return 0;
    int add=len[idc]-len[ida]-st+1;
    rep(i,1,add) a[i]='0';
    for(int i=len[ida],j=add;i>=1;i--) a[++j]=S[ida][i];
    int la=len[ida]+add,lc=len[idc];
    for(int i=len[idc],j=0;i>=1;i--){
        c[++j]=S[idc][i];
    }
    if(la>lc) return 0;
    if(la==lc){
        for(int i=la;i>=1;i--){
            if(a[i]==c[i]) continue;
            if(a[i]>c[i]) return 0;
            break;
        }
    }
    int bit=0;
    rep(i,1,la){
        c[i]-=bit;
        if(c[i]<a[i]){
            c[i]+=10;
            bit=1;
        }
        else bit=0;
        a[i]=c[i]-a[i]+'0';
    }
    int i=0;
    for(i=la;i>=1&&a[i]=='0';i--) ;
    if(i>=1){
        len[3]=i;
        for(int d=1,u=i;d<=u;d++,u--){
            swap(a[d],a[u]);
        }
        return add;
    }
    return 0;
}
int ck(int idb){
    int post=len[3],posb=len[idb];
    while(a[post]=='0') post--;
    while(S[idb][posb]=='0') posb--;
    while(post>=1&&posb>=1){
        if(a[post]==S[idb][posb]){
            post--,posb--;
            continue;
        }
        break;
    }
    return post==0&&posb==0;
}
int main(){
    int t;scanf("%d",&t);
    while(t--){
        scanf("%s%s%s",S[0]+1,S[1]+1,S[2]+1);
        len[0]=strlen(S[0]+1),len[1]=strlen(S[1]+1),len[2]=strlen(S[2]+1);
        ctc=max(0,max(len[0],len[1])+3-len[2]);
        for(int i=len[2]+1;i<=len[2]+ctc;i++){S[2][i]='0';}
        len[2]+=ctc;
        z=ctc; flag=0;
        int l1,l2;
        if(S[2][1]=='1'&&(l1=deal(2,0,2))){
            if(ck(1)){
                x=l1,y=len[3]-len[1],flag=1;
            }
        }
        if(l1=deal(2,0,1)){
            if(ck(1)){
                x=l1,y=len[3]-len[1],flag=1;
            }
        }

        if(S[2][1]=='1'&&(l1=deal(2,1,2))){
            if(ck(0)){
                y=l1,x=len[3]-len[0],flag=1;
            }
        }
        if(l1=deal(2,1,1)){
            if(ck(0)){
                y=l1,x=len[3]-len[0],flag=1;
            }
        }
        if(flag) printf("%d %d %d\n",x,y,z);
        else printf("-1\n");
    }
    return 0;
}
/*

40
23 39 62
40500 643 1048
23 39 62
2 31 51
1 1 1
20 49 5010000
20 49 5100000
2000000 490000000000000000000 51
200 490000000 51
2000000 49000 51
40500 643 1048
6003000000 101003 61040030000
19954009 800760010 10003001
5 6 11
1000000000000000000000 2 3
11111111 11 11111121000
9913293911030092 325365190001 9945830430030192000
99132939110300920000000000 3253651900010000000000 9945830430030192000
3 5 53
102 9080 1010000
*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值