hdu5920
题目
给你一个可能有1000位的数字,让你用不超过50个的回文串数字的和来表示它。
思路
整体思路就是对于一个数字,尽量把它构造成很长的回文数字,然后减去这个数字,最后一定能化成“x0000000。。。”这样的数字,而这样的数字一定能够化成3个回文数字的和,例如80000=77777+2222+1.
对于第一个尽量构造最长的回文串,例如5234247,中间位是4,我构造出5234325,但是后者比前者大,所以在第一个不相等的对称位置我们都取较小的数,这样的数字一定比原来的小,也就是5224225,然后减去它,已知进行这样的操作,当然还有620的情况,会构造出020,是不对的,要考虑首位是0的情况,用555代替,然后xjb搞就出来了。。。。
代码
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
char s[1010];
char temp[1010];
char ans[50][1010];
int num=0;
#define dlen 4
#define MAXN 9999
struct BigNum
{
int a[1100];
int len;
BigNum()
{
len=1;
memset(a, 0, sizeof(a));
}
BigNum(const char* s)
{
int t, k, index, L, i;
memset(a, 0, sizeof(a));
L = strlen(s);
len = L/dlen;
if(L%dlen) len++;
index = 0;
for(i=L-1; i>=0; i-=dlen)
{
t = 0;
k = i - dlen + 1;
if(k<0) k=0;
for(int j=k; j<=i; j++)
t=t*10+s[j]-'0';
a[index++] = t;
}
}
BigNum(BigNum & T)
{
len = T.len;
memset(a, 0, sizeof(a));
for(int i=0; i<len; i++) a[i] = T.a[i];
}
BigNum& operator=(const BigNum& T)
{
len = T.len;
memset(a, 0, sizeof(a));
for(int i=0; i<len; i++) a[i] = T.a[i];
return *this;
}
bool operator>(const BigNum& T)
{
int ln;
if(len>T.len) return true;
else if(len==T.len)
{
ln = len -1;
while(a[ln]==T.a[ln]&&ln>=0) ln--;
if(ln>=0 && a[ln]>T.a[ln]) return true;
else return false;
}
return false;
}
BigNum operator-(const BigNum& T)
{
int j, big;
bool flag;
BigNum t1, t2;
if(*this>T)
{
t1 = *this;
t2 = T;
flag = 0;
}
else
{
t1 = T;
t2 = *this;
flag = 1;
}
big = t1.len;
for(int i=0; i<big; i++)
{
if(t1.a[i]<t2.a[i])
{
j=i+1;
while(t1.a[j]==0)
j++;
t1.a[j--]--;
while(j>i)
t1.a[i--]+=MAXN;
t1.a[i]+=MAXN+1-t2.a[i];
}
else t1.a[i]-=t2.a[i];
}
t1.len = big;
while(t1.a[t1.len-1]==0 && t1.len>1)
{
t1.len--;
big--;
}
if(flag)
t1.a[big-1]=0-t1.a[big-1];
return t1;
}
void print()
{
printf("%d", a[len-1]);
for(int i=len-2; i>=0; i--)
{
printf("%04d", a[i]);
}
}
};
void getmin(char *aa,char *bb,char* cc)
{
BigNum a(aa);
BigNum b(bb);
BigNum c;
c=a-b;
sprintf(cc,"%d",c.a[c.len-1]);
int now=strlen(cc);
for(int i=c.len-2; i>=0; i--)
{
sprintf(cc+now, "%04d", c.a[i]);
now+=4;
}
}
int solve()
{
char a[1010];
strcpy(a,s);
while(1)
{
int flag=0;
if(strlen(a)==1)
{
strcpy(temp,a);
break;
}
if(a[0]!='0')
for(int i=1; i<strlen(a); i++)
if(a[i]!='0')
{
flag=1;
break;
}
if(!flag)
{
strcpy(temp,a);
break;
}
int k=(strlen(a)-1)/2;
if((strlen(a)-1)%2==1)
{
int p;
char b[1010];
if(a[k]!=a[k+1])
{
b[k]=b[k+1]=min(a[k],a[k+1]);
p=k+1;
for(int i=1; i<=k; i++)
{
if(i!=p)
b[k-i]=b[k+i+1]=a[k-i];
else
b[k-i]=b[k+i+1]=a[k+1+i];
}
}
else
{
p=1;
while((a[k-p]==a[k+p+1])&&(p<=k+1)) p++;
b[k]=b[k+1]=a[k];
for(int i=1; i<=k; i++)
{
if(i!=p)
b[k-i]=b[k+i+1]=a[k-i];
else
{
b[k-i]=b[k+i+1]=min(a[k-i],a[k+1+i]);
if(b[k-i] == '0' && k-i == 0)
{
b[k-i]=b[k+i]=max(a[k-i],a[k+i])-1;
}
}
}
}
b[strlen(a)]='\0';
char c[1010];
getmin(a,b,c);
strcpy(ans[num],b);
num++;
strcpy(a,c);
}
else
{
int p=1;
while((a[k+p]==a[k-p])&&(p<=k+1)) p++;
char b[1010];
for(int i=0; i<=k; i++)
{
if(i==p)
{
b[k-i]=b[k+i]=min(a[k-i],a[k+i]);
if(b[k-i] == '0' && k-i == 0)
{
b[k-i]=b[k+i]=max(a[k-i],a[k+i])-1;
}
}
else
b[k-i]=b[k+i]=a[k-i];
}
b[strlen(a)]='\0';
char c[1010];
getmin(a,b,c);
strcpy(ans[num],b);
num++;
strcpy(a,c);
}
}
if(strlen(temp)==1)
{
if(temp[0]!='0')
{
strcpy(ans[num],temp);
num++;
}
return num;
}
else
{
char aim=temp[0]-1;
if(aim=='0') aim='9';
char aim2='0'+('9'-aim);
char d[1010];
d[0]='1',d[1]='\0';
strcpy(ans[num],d);
num++;
if(temp[0]=='1')
{
for(int i=0; i<strlen(temp)-1; i++)
d[i]=aim;
d[strlen(temp)-1]='\0';
strcpy(ans[num],d);
num++;
return num;
}
else
{
for(int i=0; i<strlen(temp); i++)
d[i]=aim;
d[strlen(temp)]='\0';
strcpy(ans[num],d);
num++;
for(int i=0; i<strlen(temp)-1; i++)
d[i]=aim2;
d[strlen(temp)-1]='\0';
strcpy(ans[num],d);
num++;
return num;
}
}
}
int main()
{
int T;
scanf("%d",&T);
int kase=1;
while(T--)
{
scanf("%s",s);
num=0;
solve();
printf("Case #%d:\n",kase++);
printf("%d\n",num);
for(int i=0; i<num; i++)
printf("%s\n",ans[i]);
}
return 0;
}