http://acm.hdu.edu.cn/showproblem.php?pid=5920
Problem Description
Everyone hates ugly problems.
You are given a positive integer. You must represent that number by sum of palindromic numbers.
A palindromic number is a positive integer such that if you write out that integer as a string in decimal without leading zeros, the string is an palindrome. For example, 1 is a palindromic number and 10 is not.
Input
In the first line of input, there is an integer T denoting the number of test cases.
For each test case, there is only one line describing the given integer s (1≤s≤101000).
Output
For each test case, output “Case #x:” on the first line where x is the number of that test case starting from 1. Then output the number of palindromic numbers you used, n, on one line. n must be no more than 50. en output n lines, each containing one of your palindromic numbers. Their sum must be exactly s.
Sample Input
2 18 1000000000000
Sample Output
Case #1: 2 9 9 Case #2: 2 999999999999 1
Hint
9 + 9 = 18 999999999999 + 1 = 1000000000000
题意:给出一个10^1000的大数n,要求分成若干个数,要求这些数都是回文数,且和为n
题解:既然是sj,可以先一半一半地进行构造。先取一半将其变为回文数,如将16835构造成16861,然后判断大小进行相加减,注意一下一些细节,如不够相减要借位等等。具体看代码吧。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 1e3 + 5;
char s[maxn];
int ans[50][maxn],temp[maxn]; //ans记录答案,temp为操作数组
int a[maxn],b[maxn]; //a为被减数数组
int sum[60],cc[maxn]; //sum记录每个回文数的长度,cc用于细节
void jian()
{
}
int main()
{
int i,j,t,len;
scanf("%d",&t);
int ca = 1;
int mark;
while(t--)
{
mark = 0;
int tel = 0;
scanf("%s",s);
int len = strlen(s);
for(int i = 0; i < len; i++){
a[i] = s[i]-'0';
temp[i] = a[i];
}
int l = len;
int cnt1 = 0;
//----------------------预处理
while(1){
int k1 = 0;
for(int i = 0; i < l; i++){ //被减数数组更新
a[i] = temp[i];
}
for(int i = l-1; i >= 0; i--){ //每次以被减数数组的一半构造回文数
if(k1 == l/2) break;
temp[i] = temp[l-i-1];
k1++;
}
for(int i = 0; i < l; i++){ //判断减数和被减数大小
//从最高位开始比较
if(a[i] == temp[i]) continue;
if(a[i] > temp[i]) break;
if(a[i] < temp[i]){
//找到被减数小的那个高位,往前遍历,如果当前位置为0,说明无法借位就继续往前
//找到第一个不为零的高位另其减一,那么减数一定小于被减数
for(int j = i-1; j >= 0; j--){
if(temp[j] == 0) continue;
temp[j]--;
temp[l-j-1] = temp[j];
break;
}
break;
}
}
if(temp[l-1] == 0){ //这步表示当前减数为0,那么被减数一定是1000....的状态,直接特判构造1,999999...
mark = 1;
tel = l-1;
for(int i = 0; i < tel; i++){
cc[i] = 9;
}
break;
}
for(int i = 0; i < l; i++){
ans[cnt1][i] = temp[i];
}
sum[cnt1] = l;
cnt1++;
int we = 0;
for(int i = l-1; i >= 0; i--){
b[we] = a[i] - temp[i];
we++;
}
for(int i = 0; i < we; i++){
while(b[i] < 0){
b[i+1] = b[i+1]-1;
b[i] = b[i]+10;
}
}
int kk = 0;
for(int i = we-1; i >= 0; i--)
temp[kk] = b[i],kk++;
int pos;
int cnt2 = 0;
for(int i = 0; i < kk; i++){//ȥ??ǰ??
if(temp[i] == 0) continue;
else{
for(int j = i; j < kk; j++){
temp[cnt2] = temp[j];
cnt2++;
}
break;
}
}
//for(int i = 0; i < l; i++) printf("%d",b[i]);
/*for(int i = pos-1; i >= 0; i--){
temp[cnt2] = b[i];
cnt2++;
}*/
if(cnt2==0) break;
int flag = 0;
for(int i = 0; i <= cnt2/2; i++){
if(temp[i] == temp[cnt2-i-1]) continue;
else{
flag = 1;
break;
}
}
if(flag == 0){
for(int i = 0; i < cnt2; i++){
ans[cnt1][i] = temp[i];
}
sum[cnt1] = cnt2;
cnt1++;
break;
}
l = cnt2;
}
if(mark == 1){
printf("Case #%d:\n%d\n",ca++,cnt1+2);
printf("1\n");
for(int i = 0; i < tel; i++){
printf("%d",cc[i]);
}
printf("\n");
for(int i = 0; i < cnt1; i++){
for(int j = 0; j < sum[i]; j++){
printf("%d",ans[i][j]);
}
printf("\n");
}
continue;
}
printf("Case #%d:\n%d\n",ca++,cnt1);
for(int i = 0; i < cnt1; i++){
for(int j = 0; j < sum[i]; j++){
printf("%d",ans[i][j]);
}
printf("\n");
}
}
}