Contest Round #451 (Div. 2)F/Problemset 898F Restoring the Expression
题意:
有一个a+b=c的等式,去掉两个符号,把三个数连在一起得到一个数
给出这个数,要求还原等式,length <= 1e6
三个数不能含有前导0,保证有解
解法:
铁头过题法,分类然后各种判断
我分了5种情况
0.开头字符为0, 那么结果一定是0+a=a的形式
然后4种情况
1.len(a) >= len(b) 且 len(c) == len(a)
2.len(a) <= len(b) 且 len(c) == len(b)
3.len(a) >= len(b) 且 len(c) == len(a) + 1
4.len(a) <= len(b) 且 len(c) == len(b) + 1
前两种(没有进位)判断的情况:
(1)三个数如果长度不为1,那么最高位不能为0
(2)len(a) != len(b) 时, 若max(a, b)的最高位为x,
则c的最高位,应该为x或者x+1
(3)满足上面两种情况,开始检验a+b的每一位与c的每一位是否相等
后两种(有进位)判断的情况:
(1)三个数如果长度不为1,那么最高位不能为0
(2)c的最高位必须是1
(3)满足上面两种情况,开始检验a+b的每一位与c的每一位是否相等
时间复杂度未知,但是实际运行效果,时空复杂度都是超赞的!
(整理了一下代码似乎精简过度影响了可读性了...)
1 #include <stdio.h> 2 #include <string.h> 3 4 int n; 5 6 char s[1000010]; 7 8 int i, j, k, p, l, r; 9 10 int print() { 11 int i = 1; 12 for (; i <= l; i ++) 13 putchar(s[i]); 14 putchar('+'); 15 for (; i <= r; i ++) 16 putchar(s[i]); 17 putchar('='); 18 for (; i <= n; i ++) 19 putchar(s[i]); 20 return 1; 21 } 22 23 int check(int s1, int s2) { 24 for (int i = s1, j = s2, k = n, t = 0; k > s2; k --) { 25 if ((s[i] + s[j] + t - 96) % 10 != s[k] - 48) 26 return 0; 27 t = (s[i] + s[j] + t - 96) / 10; 28 i --, j --; 29 if (i <= 0) i = 0; 30 if (j <= s1) j = 0; 31 } 32 return 1; 33 } 34 35 int judge() { 36 if (l + 1 != r && s[l + 1] == '0') return 0; 37 if (p) {if (s[r + 1] != k) return 0;} 38 else if (i != j && (k != s[r + 1] && k + 1 != s[r + 1])) return 0; 39 if (!check(l, r)) return 0; 40 return print(); 41 } 42 43 int main() { 44 gets(s + 1); 45 n = strlen(s + 1); 46 s[0] = '0'; 47 48 l = 1, r = n - n / 2; 49 if (s[1] == '0') { 50 print(); 51 return 0; 52 } 53 54 for (i = 1 + (n & 1 ? 0 : 1), j = (n - i) / 2, r = n - j; i <= n / 3; i += 2, j --, r ++) { 55 l = j, k = s[1]; 56 if (judge()) return 0; 57 l = i, k = s[l + 1]; 58 if (judge()) return 0; 59 } 60 61 p = 1, k = 49; 62 for (i = 1 + (n & 1 ? 1 : 0), j = (n - i) / 2, r = n - j - 1; i <= n / 3 - (n % 3 == 0); i += 2, j --, r ++) { 63 l = j; 64 if (judge()) return 0; 65 l = i; 66 if (judge()) return 0; 67 } 68 }