「hdu6646」A + B = C【哈希】

A + B = C

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1192 Accepted Submission(s): 262
Special Judge

Problem Description

Hi everyone! Welcome to the Stage 7 7 7 of this series of training contests. Cuber QQ is the problem settler of this contest; he has prepared 11 11 11 problems for you and wishes you to enjoy it. Good luck!

As the first problem of this contest, Cuber QQ thought that it’s reasonable to start with an easy one, so he modified the famous A + B A + B A+B problem by a little bit, so that it’s easy enough but not that trivial.

Given a , b , c a,b,c a,b,c , find an arbitrary set of x , y , z x,y,z x,y,z such that a × 1 0 x + b × 1 0 y = c × 1 0 z a\times 10^x+b\times 10^y=c\times 10^z a×10x+b×10y=c×10z and 0 ≤ x , y , z ≤ 1 0 6 0\leq x,y,z\leq 10^6 0x,y,z106.

Input

The input consists of multiple test cases, starting with an integer t ( 1 ≤ t ≤ 100 ) t (1\leq t\leq 100) t(1t100), denoting the number of test cases.

For each test case, there are three space-separated integers, a , b , c a,b,c a,b,c respectively ( 1 ≤ a , b , c ≤ 1 0 100000 ) (1\leq a,b,c\leq 10^{100000}) (1a,b,c10100000).

Output

For each test case, please output three space-separated integers x , y , z x,y,z x,y,z. If there are multiple solutions, print any of them.

In case there are no solutions, please output − 1 −1 1 as a single line.

Sample Input

3
23 39 62
2 31 51
1 1 1

Sample Output

0 0 0
1 0 0
-1

Hint

HDOJ may give ambiguous feedback due to the compatibility issue of our checker. If you see “System Error”, please think of it as “Wrong Answer”.

Source

2019 Multi-University Training Contest 7

题意

  • 就是给你三个长度为 1 0 5 10^5 105的数 a , b , c a,b,c a,b,c,让你求三个数 x , y , z x,y,z x,y,z,且 0 ≤ x , y , z ≤ 1 0 6 0\leq x,y,z \leq 10^6 0x,y,z106,使得 a × 1 0 x + b × 1 0 y = c × 1 0 z a\times 10^x+b\times 10^y=c\times 10^z a×10x+b×10y=c×10z

题解

  • 首先根据常识可知,两个数 a , b a,b a,b相加等于另外一个数 c c c,记三个数长度分别为 l e n a , l e n b , l e n c len_a,len_b,len_c lena,lenb,lenc那么 l e n c len_c lenc的长度要么是 m a x ( l e n a , l e n b ) max(len_a,len_b) max(lena,lenb),要么是 m a x ( l e n a , l e n b ) + 1 max(len_a,len_b)+1 max(lena,lenb)+1,所以考虑将 a a a或者 b b b高位与c高位或c第二高位处对其,然后去 c h e c k check check a + b a+b a+b可不可能等于 c c c【因为枚举a对齐的时候b也可能需要左移使等式成立】所以就是枚举四种情况去 c h e c k check check就行了
  • 然后 c c c最开始需要处理一下,使得他最够长,然后才能 c − a c-a ca是个正数,所以很容易想到使得c的长度变为 m a x ( l e n c , m a x ( l e n a , l e n b ) + 1 ) max(len_c,max(len_a,len_b)+1) max(lenc,max(lena,lenb)+1),但是注意c的初始值也有可能是这种情况: a + b a+b a+b的值后面有很多 0 0 0,去掉这些 0 0 0得到 c c c,比如说 a = 1111 , b = 100 , c = 1112 a=1111,b=100,c=1112 a=1111,b=100,c=1112这种情况下你不能仅仅在 c c c后面加一个 0 0 0,你需要加两个 0 0 0,换句话说,假设 a , b a,b a,b的后缀 0 0 0的数量分别为 z e r o a , z e r o b zero_a,zero_b zeroa,zerob c c c的长度应该初始化为 m a x ( l e n c , m a x ( l e n a − z e r o a , l e n b − z e r o b ) + m a x ( z e r o a , z e r o b ) + 1 ) max(len_c,max(len_a-zero_a,len_b-zero_b)+max(zero_a,zero_b)+1) max(lenc,max(lenazeroa,lenbzerob)+max(zeroa,zerob)+1),如图所示。
    在这里插入图片描述
  • 然后检查 a + b a+b a+b是否等于 c c c可以使用哈希,就不需要用高精模拟啦,由于这题好像有点卡常,所以没用三哈希,用的双哈希,也有可能是我的哈希不够优秀

代码

#pragma GCC optimize(3)
#include<bits/stdc++.h>

using namespace std;
const int maxn=2e5+10;

struct Hash{
    int base[4],mod[4];
    int tot,hash[4][maxn],pw[4][maxn]; 
    Hash() {
        tot=0;
        for(int i=1;i<=3;i++) pw[i][0]=1;
        base[1]=10;base[2]=10;base[3]=10;
        mod[1]=1e9+7;mod[2]=998244353;mod[3]=1e9+9;
    }
    void init() {tot=0;}
    void insert(int c) {
        tot++;
        for(int i=1;i<=2;i++) hash[i][tot]=(1LL*hash[i][tot-1]*base[i]+c)%mod[i];
        for(int i=1;i<=2;i++) pw[i][tot]=(1LL*pw[i][tot-1]*base[i])%mod[i];
    }
    int query(int l,int r,int type) { 
        if(l==1) return hash[type][r];
        return (hash[type][r]-(1LL*hash[type][l-1]*pw[type][r-l+1]%mod[type])+mod[type])%mod[type];
    }

    friend bool check(Hash &a,int l1,int r1,Hash &b,int l2,int r2,Hash &c,int l3,int r3) {
        for(int i=1;i<=2;i++) if((a.query(l1,r1,i)+b.query(l2,r2,i))%a.mod[i]!=c.query(l3,r3,i)) return false;
        return true;
    }

}h[4];

char s[4][maxn];
int prel[4]; //记录字符串长度

int main()
{
    int t;scanf("%d",&t);
    for(int cas=1;cas<=t;cas++) {
        int suf=0,pre=0;
        for(int i=1;i<=3;i++) scanf("%s",s[i]+1),prel[i]=strlen(s[i]+1),h[i].init();
        for(int i=1;i<=2;i++) {
            int cnt=0;
            for(int j=prel[i];s[i][j]=='0';j--) cnt++;
            suf=max(suf,cnt); //0
            pre=max(pre,prel[i]-suf); //非0
        }
        int des=max(prel[3],pre+suf+1);  //初始化长度
        for(int i=1;i<=3;i++) for(int j=1;j<=des;j++) h[i].insert(j<=prel[i]?s[i][j]-'0':0);
        int x,y,z=des-prel[3];bool ok=false;
        for(int i=prel[2];i<=des;i++) { //将a与c对齐,枚举b的长度
            if(check(h[1],1,h[1].tot,h[2],1,i,h[3],1,h[3].tot)) { 
                x=des-prel[1],y=i-prel[2],ok=true;
                break;
            }
            if(check(h[1],1,h[1].tot-1,h[2],1,i,h[3],1,h[3].tot)) {
                x=des-prel[1]-1,y=i-prel[2],ok=true;
                break;
            }
        }
        if(ok) {printf("%d %d %d\n",x,y,z);continue;}
        for(int i=prel[1];i<=des;i++) {  //将b与c对齐,枚举a的长度
            if(check(h[1],1,i,h[2],1,h[2].tot,h[3],1,h[3].tot)) {
                x=i-prel[1],y=des-prel[2],ok=true;
                break;
            }
            if(check(h[1],1,i,h[2],1,h[2].tot-1,h[3],1,h[3].tot)) {
                x=i-prel[1],y=des-prel[2]-1,ok=true;
                break;
            }
        }
        if(ok) printf("%d %d %d\n",x,y,z);
        else printf("-1\n");
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值