hdu 5920 Ugly Problem(构造题)

Ugly Problem

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



思路:回文数就是从前数第几位和从后数第几位都相同的数

那么大致就是我们可以先把这个数str的一半长所代表的数s找到,然后用s-1来构造回文数ss,ss肯定比原先的数str要小,因此这样构造的ss就是比较优的解了

(其实比如说156,可以构造151,而我的算法是141,所以我的最后可能会比最优的算法多构造一个数)

代码:

#include<bits/stdc++.h>
using namespace std;

struct node//存储构造的答案
{
    string s;
} p[100];

int tmpa[10000],tmpb[10000],c[10000];

string sub(string a,string b)//大整数减法
{
    int i,j,k,s,flag=1;
    memset(tmpa,0,sizeof(tmpa));
    memset(tmpb,0,sizeof(tmpb));
    memset(c,0,sizeof(c));
    string ans="";
    if(a.size()<b.size()||(a.size()==b.size()&&a.compare(b)<0))
    {
        string tmp=a;
        a=b;
        b=tmp;
        flag=0;
    }
    while(a.length()>b.length())
        b='0'+b;
    int len=a.length();
    for(i=0; i<len; ++i)
    {
        tmpa[i]=a[i]-'0';
        tmpb[i]=b[i]-'0';
    }
    for(i=len-1; ~i; --i)
    {
        if(tmpa[i]>=tmpb[i])
            c[i]=tmpa[i]-tmpb[i];
        else
        {
            c[i]=10+tmpa[i]-tmpb[i];
            --tmpa[i-1];
        }
    }
    for(i=0; i<len-1; ++i)
        if(c[i])
            break;
    for(j=i; j<len; ++j)
        ans=ans+(char)(c[j]+'0');
    if(!flag)
        ans='-'+ans;
    return ans;
}

bool judge(string s)//判断s是否是回文数
{
    for(int i=0; i<s.length()/2; ++i)
        if(s[0+i]!=s[s.length()-1-i])
            return false;
    return true;
}

string pow(int n)//10的n次方
{
    string s="1";
    while(n--)
        s+="0";
    return s;
}

int main()
{
    ios::sync_with_stdio(false);
    int t,k=0;
    cin>>t;
    while(++k<=t)
    {
        string str;
        cin>>str;
        int tot=0;
        while(str.length()>1)
        {
            if(judge(str))//如果str为回文数
            {
                p[++tot].s=str;
                str="0";
                break;
            }
            if(str==pow(str.length()))//如果str为'1000000....'这种形式
            {
                p[++tot].s="1";
                p[++tot].s=sub(str,"1");
                str="0";
                break;
            }
            string s="";
            int mid=str.length()/2;
            if(str.length()&1)//奇数长度
            {
                string ss;
                for(int i=0; i<=mid; ++i)
                    s+=str[i];
                s=sub(s,"1");
                ss=s;
                for(int i=mid-1; ~i; --i)
                    s+=ss[i];
            }
            else//偶数长度
            {
                if(str.length()==2&&str[0]=='1')//如果str最后为'1x'(x>0)这种形式
                    s="11";
                else
                {
                    for(int i=0; i<mid; ++i)
                        s+=str[i];
                    s=sub(s,"1");
                    for(int i=mid-1; ~i; --i)
                        s+=s[i];
                }
            }
            str=sub(str,s);
            p[++tot].s=s;
        }
        if(str!="0")
            p[++tot].s=str;
        cout<<"Case #"<<k<<":"<<endl;
        cout<<tot<<endl;
        for(int i=1; i<=tot; ++i)
            cout<<p[i].s<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值