題目大意是:
給定一個數N(10 ……10^9),求出A,B,A的開頭數字不能為0,B的開頭數字可以為0,B為A去掉一個10進位位後得到的數字
及A的數位一定是B的數位+1,並且A + B = N
我們可以遍曆,去掉A的第pre位後得到B,
我們假設pre位前面的為x,pre位為y,pre位後為z
即A 為 xyz,那麼B為xz
這個時候y的權為flag = 10^pre
因為A + B = N
所以xy * flag + x * flag + 2 * z = N
所以一定滿足(N - 2 * z)% flag == 0;(對z的遍曆初始化z = (N - N / flag* flag) / 2,並每次z+=flag/2,可以保證這個條件成立並使演算法複雜度降到很低,注意當N為奇數時
該條件基本上不成立,但是當flag = 1及去掉的就是各位的時候可以成立)
並且x,y中至少有一個不為0,所以(N - 2 * z) >= flag;
並且N - 2 * z >0;
並且z是比權flag要小的
並且因為y是要被去掉的數字,所以y一定不能大於10
因為xy * flag + x * flag + 2 * z = N =》 x = (N - 2 * z) / 11; Y = (N - 2 * z) % 11;
根據以上的這些條件就可以算出所有合格A,B
但還是要注意結果中有重複的比如12 = 11 + 1;可以從11中去掉十位得到1,還可以從11中去掉各位得到1
所以結果中有重複,需去重
結合My Code再次分析
My Code:
#include<stdio.h>int stack[1001];int snum;int add(int x, int y, int z, int pre)//xyz即為答案,注意z的位元為pre-1{int i, array[11];array[pre] = y; //y是確定的第pre為for(i = 1; i < pre; i ++) //z是pre後面的數字{array[i] = z % 10;z /= 10;}for(i = pre + 1; i <= 10; i ++)//{array[i] = x % 10;x /= 10;}stack[++ snum] = 0; //算出結果存如棧中for(i = 10; i >= 1; i --){stack[snum] *= 10;stack[snum] += array[i];}return 0;}int Max(int a, int b){return a > b ? a : b;}int find(int pre, int n){int i;int flag = 1;int max;if(pre == 0)return 0;for(i = 1; i < pre; i ++) //算出權值flag *= 10;if(pre != 1 && n % 2 == 0 || pre == 1)//只有當flag = 1和n不為奇數的時候才能保證(N - 2 * z)% flag == 0;{max = Max(flag / 2, 1);for(i = (n - n / flag * flag) / 2; i < flag; i += max)//在(N - 2 * z)% flag == 0的前提下,只有z+=flag*2才能繼續滿足條件{if(i * 2 >= n)break;if((n - i * 2) < flag)break;if((n - i * 2) / flag % 11 != 10){add((n - i * 2) / flag / 11, (n - i * 2) / flag % 11, i, pre);//算出了x,y,z,加入棧}}}return find(pre - 1, n);}int swap(int &a, int &b){a ^= b;b ^= a;a ^= b;return 0;}int sort(){int i, j;for(i = 1; i < snum; i ++)for(j = i + 1; j <= snum; j ++){if(stack[i] == stack[j])//存在相同答案就去掉相同答案{stack[j] = stack[snum];snum --;j --;}}for(i = 1; i <= snum; i ++) //排序{for(j = i + 1; j <= snum; j ++){if(stack[i] > stack[j]){swap(stack[i], stack[j]);}}}return 0;}int prin(int x, int n){int y = n - x, i; //由A算出B,但是B的位元一定要有A的位元-1,否則前面補0int array[11], tail = 0;printf("%d + ", x);while(x >= 10){array[++ tail] = y % 10;y /= 10;x /= 10;}for(i = tail; i >= 1; i --)printf("%d", array[i]);printf(" = %d\n", n);return 0;}int main(){int n;int i;while(scanf("%d", &n) != EOF){snum = 0;find(10, n); //從去掉第10為開始找sort();printf("%d\n", snum); //坑爹的地方,因為總數沒輸出導致我一直wa,調試了好久,唉for(i = 1; i <= snum; i ++){prin(stack[i], n);}}return 0;}