原题:
Given a,b,c, find an arbitrary set of x,y,z such that a*10^x+b*10^y=c*10^z and 0≤x,y,z≤10^6.
给你三个高精度数a、b、c,要求找出任意一组x、y、z满足a*10^x+b*10^y=c*10^z
首先需要发现一个性质
乘上10的幂会往数的最后面填上0,而不会对最前面的位造成影响
一开始我的思路是考虑三个数的个位,这种就很麻烦了
(听说能忽略前导零然后讨论,但我总觉得是假做法)
考虑前面位的话,就只有几种情况:
①a、b、c对齐
②a和b对齐,然后相加进一位,然后和c对齐
③a和c对齐,b在中间
④a加上b进一位和c对齐
⑤⑥同③④
(注意重要性质:加法最多只会进1,最多增加1位)
前两个可以a+b然后判断
后两个可以c-a然后判断
(这里的a、b、c都是指对齐过的)
所有情况都判断一下找到一组解就vans了
接下来就是喜闻乐见的码农时间
因为情况比较多,所以用工具函数,数组作为参数,以a[0]作为a的长度,这样是非常舒服的
一开始写的是二分,即a和c对齐后二分b左移的位数
但是又100组数据,1e6*log1e6*100肯定T了
实际上不用二分,直接减然后判断是比较简单的
另外,第一次写的时候左移是用函数里的参数控制的,这样写前两个还好,后四个情况再带上减法会及其麻烦
写到后期把减法加进去后代码直接崩溃了,前言不搭后语
最后额外开三个高精度数,写一个左移函数,用函数额外的一个参数表示高精度运算过后的结果放到哪里
这样写下来一气呵成,很顺利
所以说代码自动化和通用工具函数还是很有用的
(一开始写屎的锅就是因为中午没睡一脸蒙蔽=。=)
总结经验:
1.有时候不要贪图局部的代码方便
尤其是不要偷懒,为了想起来简单而放弃写通用函数
2.结构化程序设计(或者工具函数、代码自动化)带来的加成是惊人的
甚至可以为了这些放弃别的东西,比如代码复杂度,比如常数
3.敢于重构代码
又一个实例证明重构利大于弊
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int a[3100000],b[3100000],c[3100000],d[3100000]; 8 int e[3100000],f[3100000],g[3100000]; 9 void clr(int x[]){ 10 for(int i=1;i<=x[0];++i) x[i]=0; 11 x[0]=0; 12 } 13 void rvs(int x[]){ 14 clr(d); 15 d[0]=x[0]; 16 for(int i=1;i<=d[0];++i) d[i]=x[i]; 17 for(int i=1;i<=d[0];++i) x[i]=d[d[0]-i+1]; 18 } 19 void rd(int x[]){ 20 clr(x); 21 char ch=getchar(); 22 while(ch<'0'||ch>'9') ch=getchar(); 23 while(ch>='0'&&ch<='9'){ 24 x[++x[0]]=ch-'0'; 25 ch=getchar(); 26 } 27 rvs(x); 28 } 29 void cpy(int x[],int y[]){ 30 clr(y); 31 y[0]=x[0]; 32 for(int i=1;i<=x[0];++i) y[i]=x[i]; 33 } 34 void lm(int x[],int y,int z[]){ 35 cpy(x,z); 36 for(int i=z[0];i>=1;--i) z[i+y]=z[i]; 37 for(int i=1;i<=y;++i) z[i]=0; 38 z[0]+=y; 39 } 40 void pls(int x[],int y[],int z[]){ 41 clr(z); 42 z[0]=max(x[0],y[0]); 43 for(int i=1;i<=x[0];++i) z[i]+=x[i]; 44 for(int i=1;i<=y[0];++i) z[i]+=y[i]; 45 for(int i=1;i<=z[0];++i)if(z[i]>=10){ 46 z[i+1]+=z[i]/10; 47 z[i]%=10; 48 } 49 if(z[z[0]+1]) ++z[0]; 50 } 51 void mns(int x[],int y[],int z[]){ 52 cpy(x,z); 53 for(int i=1;i<=z[0];++i){ 54 z[i]-=y[i]; 55 if(z[i]<0){ 56 z[i]+=10; 57 --z[i+1]; 58 } 59 } 60 while(!z[z[0]]) --z[0]; 61 } 62 int cmp(int x[],int y[]){ 63 if(x[0]<y[0]) return -1; 64 if(x[0]>y[0]) return 1; 65 for(int i=x[0];i>=1;--i){ 66 if(x[i]<y[i]) return -1; 67 if(x[i]>y[i]) return 1; 68 } 69 return 0; 70 } 71 void ot(int x,int y,int z){ 72 int mn=min(x,min(y,z)); 73 printf("%d %d %d ",x-mn,y-mn,z-mn); 74 } 75 int chck(int x[],int y[]){ 76 if(x[0]<y[0]) return -1; 77 for(int i=y[0],j=x[0];i>=1;--i,--j) 78 if(y[i]!=x[j]) return -1; 79 for(int i=1;i<=y[0]-x[0];++i) 80 if(x[i]) return -1; 81 return x[0]-y[0]; 82 } 83 void gogogo(){ 84 int mxl=max(a[0],max(b[0],c[0])); 85 lm(a,mxl-a[0],e),lm(b,mxl-b[0],f),lm(c,mxl-c[0],g); 86 pls(e,f,d); 87 if(!cmp(d,g)){ 88 ot(mxl-a[0],mxl-b[0],mxl-c[0]); 89 return ; 90 } 91 lm(c,mxl-c[0]+1,g); 92 if(!cmp(d,g)){ 93 ot(mxl-a[0],mxl-b[0],mxl-c[0]+1); 94 return ; 95 } 96 int tmx=max(a[0]+b[0],c[0])+b[0]-1; 97 lm(a,tmx-a[0],e),lm(b,tmx-b[0],f),lm(c,tmx-c[0],g); 98 if(cmp(g,e)==1){ 99 mns(g,e,d); 100 int tmp=chck(d,b); 101 if(tmp!=-1){ 102 ot(tmx-a[0],tmp,tmx-c[0]); 103 return ; 104 } 105 } 106 if(cmp(g,f)==1){ 107 mns(g,f,d); 108 int tmp=chck(d,a); 109 if(tmp!=-1){ 110 ot(tmp,tmx-b[0],tmx-c[0]); 111 return ; 112 } 113 } 114 lm(c,tmx-c[0]+1,g); 115 if(cmp(g,e)==1){ 116 mns(g,e,d); 117 int tmp=chck(d,b); 118 if(tmp!=-1){ 119 ot(tmx-a[0],tmp,tmx-c[0]+1); 120 return ; 121 } 122 } 123 if(cmp(g,f)==1){ 124 mns(g,f,d); 125 int tmp=chck(d,a); 126 if(tmp!=-1){ 127 ot(tmp,tmx-b[0],tmx-c[0]+1); 128 return ; 129 } 130 } 131 printf("-1 "); 132 } 133 void prvs(){ 134 clr(a),clr(b),clr(c),clr(d); 135 } 136 int main(){ 137 freopen("ddd.in","r",stdin); 138 a[0]=0,b[0]=0,c[0]=0,d[0]=0; 139 int T; cin>>T; 140 while(T --> 0){ 141 prvs(); 142 rd(a),rd(b),rd(c); 143 gogogo(); 144 } 145 return 0; 146 }