题目大意是:
给定一个数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
所以结果中有重复,需去重
结合我的代码再次分析
我的代码:
#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,否则前面补0
int 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;
}