【2019杭电多校第七场1001=HDU6646】A+B=C(思维+多细节)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6646

题目


 

解题思路:


(1)先把a,c的末尾补零(a,b都是用数组存的),使它们的长度相同,比如3e5,补零后的a[]对应A[],b[]对应B[]。

那么问题转化为A+b*10^y=C,判断b能否整除(C-A),且除数是10的倍数。

但是A+M=C,可能会产生进位,所以对于A+b*10^y=C这个式子还需要分C是否有进位,所以A和C都要从下标1开始存数,当C有进位时,A还要考虑A[0]的0,所以A[0]和C[1]对应,A[1]和C[2]对应。

一些细节:

1.如果A和C的对应位,第一个不相同的数A[i]>C[i],那么这种情况下肯定无解;

2.(C-A)进行的是不借位的减法,有些位上可能是负数,要从后往前处理,得到正确的(C-A)的值;

3.(C-A)的值可能会有很多前导0,要从第一个非0的位开始和b对应位上的数开始比较,不相等那么b就无法整除(C-A);

4.有可能C的很末尾上的数不为0,但A的很末尾上的数为0, 那么(C-A)很末尾上的数就不为0,这样的话b还是无法整除(C-A)(不过这种情况不用判断也不会wa)

(2)先把b,c末尾补零,使其长度为3e5,分别对应B[],C[],对a*10^x+B=C同样分C有进位和C无进位两字情况判断a能否整除(C-B),和(1)同理。

虽然长度定的是3e5,但是A[],B[],C[]都至少开4e5左右才不会System Error,有点迷?

 

ac代码:


#include
using namespace std;
typedef long long ll;
const int maxn = 3e5;
const int maxx = 1e5+5;
const int maxt = 4e5;
char a[maxx], b[maxx], c[maxx];
int A[maxt], B[maxt], C[maxt], D[maxt];// 因为会达到A[3e5] 下标从1开始的话
int judge(int A[], int B[], int C[], int lenb) // 传入A+1或者A
{
    // A + B * 10^x = C 判断C-A能否在整除B
    for(int i = 0; i < maxn; i++) // 末尾补全0后A和C的总长度都是maxn,B的长度也是maxn
        if(A[i] != C[i])
        {
            if(C[i] < A[i]) return -1;// 从高位起, 第一个不相等的数C[i] < A[i],无解
            break;
        }
    for(int i = 0; i < maxn; i++) D[i] = C[i] - A[i];
    for(int i = maxn - 1; i> 0; i--) // 从低位开始
        if(D[i] < 0)
        {
            D[i - 1]--;
            D[i] += 10; //消除进位
        }
    int id = 0;
    while(!D[id] && id < maxn) id++;// 找到D[i]第一个非0的位
    for(int i = 0; i < lenb; i++)
        if(D[id + i] != B[i])
            return -1;//不能整除
    for(int i = lenb; i < maxn; i++)
        if(D[id+i]) return -1;//C[i]-A【i】的末尾可能有非0的数,当然不加这个判断也不会wa
    return maxn - lenb - id;
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    int t, res;
    scanf("%d", &t);
    while(t--)
    {
        memset(A, 0, sizeof(A));
        memset(B, 0, sizeof(B));
        memset(C, 0, sizeof(C));
        scanf("%s%s%s", a, b, c);
        int lena = strlen(a), lenb = strlen(b), lenc = strlen(c);
        for(int i = 0; i < lena; i++) A[i + 1] = a[i] - '0';
        for(int i = 0; i < lenb; i++) B[i + 1] = b[i] - '0';
        for(int i = 0; i < lenc; i++) C[i + 1] = c[i] - '0';
        if((res = judge(A + 1, B + 1, C + 1, lenb)) != -1)// A + B*10^x = C,C无进位
        {
            printf("%d %d %d\n", maxn - lena, res, maxn - lenc);
            continue;
        }
        if((res = judge(A, B + 1, C + 1, lenb)) != -1)//  A + B*10^x = C,C有进位
        {
            printf("%d %d %d\n", maxn - lena - 1, res, maxn - lenc);
            continue;
        }
        if((res = judge(B + 1, A + 1, C + 1, lena)) != -1)// A *10^x + B = C ,C无进位
        {
            printf("%d %d %d\n", res, maxn - lenb, maxn - lenc);
            continue;
        }
        if((res = judge(B, A + 1, C + 1, lena)) != -1 )// A *10^x + B = C ,C有进位
        {
            printf("%d %d %d\n",res, maxn - lenb - 1, maxn - lenc);
            continue;
        }
        printf("-1\n");
    }
    return 0;
}

 

 

你可能感兴趣的:(思路是个好东西,数学题)