HDU 5918 Ugly Problem(模拟)

2016 CCPC changchun(J)

题意:给你一个数字n,把n拆成不超过50个回文数字,使得拆成的回文数字之和等于n。(n可达到10的1000次方)

思路:
要求最多拆成50个数字,意味着这题必须去考虑如何拆能够尽量得到一个比较大的回文数字,这样能尽快把n变小。
方法是:对于一个数字,设长度为len,则取前半段(长度为len/2)的值减去 1 ,再翻转 , 那么就能得到一个小于 n 的最大回文数字 。(详见代码

坑点在于前导0的处理,以及字符串的一系列骚操作…
下面是代码

#include <bits/stdc++.h>
using namespace std;
string s;
vector<string> st;

string sub(string s,string tmp)//自定义减法运算,返回 s - tmp 的字符串
{
    int i=s.length()-1,j=tmp.length()-1,k;
    for(;j>=0;j--,i--)
    {
        if(s[i]<tmp[j])
        {
            s[i] = (s[i] + 10) - tmp[j] + '0';
            s[i-1]--;
        }
        else s[i] = s[i] - tmp[j] + '0';
    }
    for(;i>=0;i--)//因为 s 串的数值一定大于 tmp ,直接把小于‘0’的退位补足
    {
        if(s[i]<'0')
        {
            s[i]+=10;
            s[i-1]--;
        }
    }
    string tmp2 ;
    for(k=0;s[k]=='0';k++);//这一步是去除前导0
    tmp2 = s.substr(k);
    return tmp2;//返回s - tmp 的值(字符串形式)
}

void init()
{
    string tmp,tmp2;
    while(1)
    {
        if(s.length()<2 ||(s.length()==2&&s[0]=='1' ))break;
        //结束标志为数字范围在[019]之间,不再适用于下面的操作,需要特判
        tmp.clear();
        tmp2.clear();
        int len = s.length();
        if(len%2)
        {
            tmp+=s.substr(0,(len+1)/2);//取出前半段的数字
            tmp = sub(tmp,"1");//前半段数字减1
            tmp2 = tmp;
            reverse(tmp.begin(),tmp.end());//翻转
            tmp2 += tmp.substr((((len+1)/2)>tmp2.length())?0:1);
            st.push_back(tmp2);//接在一起就是回文数字,放进vector
            s = sub(s,tmp2);//更新当前n的值
        }
        else(同上)
        {
            tmp+=s.substr(0,len/2);
            tmp = sub(tmp,"1");
            tmp2 = tmp;
            reverse(tmp.begin(),tmp.end());
            tmp2 += tmp;
            st.push_back(tmp2);
            s = sub(s,tmp2);
        }
    }
    //下面全是特判
    if(s.length()==2)
    {
        if(s[1]=='1')
        {
            st.push_back(s);
            return;
        }
        else if(s[1]>s[0])
        {
            st.push_back("11");
            s = sub(s,"11");
            st.push_back(s);
        }
        else
        {
            st.push_back("1");
            st.push_back("9");
        }
    }
    else if(s.length()==1)
    {
        if(s[0]!='0')
            st.push_back(s);
    }
}

int main()
{
    int t,ca=1;cin>>t;
    while(t--)
    {
        cin>>s;
        printf("Case #%d:\n",ca++);
        st.clear();
        init();
        cout<<st.size()<<endl;
        for(auto ss:st)
            cout<<ss<<endl;
    }
    return 0;
}

这题只要想到如何把串的数量控制在50以内其实还是挺容易想到的,只是模拟写起来很累,需要非常细心。

转载请注明出处^ ^

猜你喜欢

转载自blog.csdn.net/mmingfunnytree/article/details/78340389