回文数

 如果一个数正着读和反着读一样大,则这个数叫做回文数,例如121是回文数,123454321是回文数。 

现给定一个正整数x,输出一个回文数y,要求y > x,并且组成x的所有数字之和与组成y的所有数字之和相等,以及y > x。

x在10^1000以内,因为数字较大,我们用字符串作为输入和输出。

如果无解,请输出Impossible。如果有多个y,输出最小的那个。

 例如: 
 输入919,输出14941 
输入1,输出Impossible


#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Test {
public:
    static void spreadFromMiddle(int &num, int *buf, int &begin, int &end)
    {
        while (num)
        {
            int value = min(9-buf[begin], num/2);
            buf[begin] += value;
            buf[end] += value;
            num -= 2*value;
            begin--;
            end++;
        }
    } 

    static void outputString(int *buf, char *output, int len)
    {
        int result = 0;
        for (int i = 0; i < len; i++)
        {
            result += buf[i];
            output[i] = buf[i] + '0';
        }
    }

    static void arrangeMidOfOddArray(int *buf, int &begin, int &end, int mid, int &num)
    {
        if (buf[mid] > 9)
        {
            if (buf[mid] & 1)
            {
                num += buf[mid] - 9;
                buf[mid] = 9;
            }
            else
            {
                num += buf[mid] - 8;
                buf[mid] = 8;
            }
        }

        begin--;
        end++;
    }

    static string palindrom(string a)
    {
        int totalNum = 0;
        int numOfChar = a.length();

        for (int i = 0; i < numOfChar; i++)
        {
            totalNum += a[i]-'0';
        }

        if (totalNum < 2 || numOfChar < 2)
        {
            return "Impossible";
        }

        int *buf = new int[numOfChar+3];
        char *output = new char[numOfChar+3];
        memset(buf, 0, (numOfChar+3)*sizeof(int));
        memset(output, 0, (numOfChar+3)*sizeof(char));

        int begin = 0;
        int end = numOfChar-1;
        int num = totalNum;
        bool success = false;
        int len = numOfChar;

        bool needExpand = false;
        int mid = len/2;

        if (!(numOfChar & 1) && (totalNum & 1))
        {
            needExpand = true;
        }

        if (!needExpand)
        {
            while ((begin < end) && (num >= 2*(a[begin]-'0')))
            {
                buf[begin] = a[begin]-'0';
                buf[end] = a[begin] - '0';
                num -= 2*(a[begin]-'0');
                begin++;
                end--;
            }
            if (begin != end)
            {
                begin--;
                end++;
            }

            if (begin == end)
            {
                buf[begin] = num;
                num = 0;

                for (int i = begin; i < len; i++)
                {
                    if (buf[i] > a[i]-'0')
                    {
                        success = true;
                        break;
                    }
                    if (buf[i] < a[i]-'0')
                    {
                        break;
                    }
                }

                if (success)
                {
                    arrangeMidOfOddArray(buf, begin, end, mid, num);
                    spreadFromMiddle(num, buf, begin, end);
                }
            }
        }

        int newEnd;
        if (!success && !needExpand)
        {
            if (num < 2)
            {
                int newBegin = begin;

                while (newBegin >= 0 && buf[newBegin] == 0)
                {
                    newBegin--;
                }
                if (newBegin > 0)
                {
                    if (mid == newBegin)
                    {
                        num += buf[newBegin];
                    }
                    else
                    {
                        num += 2*buf[newBegin];
                     }
                     buf[newBegin] = 0;
                     buf[len-1-newBegin] = 0;
                }

                newEnd = newBegin - 1;
            }
            else
            {
                newEnd = begin;

                if (begin == end)
                {
                    newEnd = begin-1;
                    num += buf[mid];
                    buf[mid] = 0;
                }
            }

            while (newEnd >= 0 && buf[newEnd] == 9)
            {
                num += 2*buf[newEnd];
                buf[newEnd] = 0;
                buf[len-1-newEnd] = 0;
                newEnd--;
            }

            if (newEnd >= 0 && num >= 2)
            {
                buf[newEnd]++;
                buf[len-1-newEnd]++;
                num -= 2;

                if (len & 1)
                {
                    begin = end = mid;
                    buf[mid] = num;
                    num = 0;

                    arrangeMidOfOddArray(buf, begin, end, mid, num);
                }
                else
                {
                    begin = mid - 1;
                    end = begin + 1;
                }

                spreadFromMiddle(num, buf, begin, end);
                success = true;
            }
        }

        if (!success)
        {
            if (totalNum & 1)
            {
                if (!(numOfChar & 1))
                {
                    len++;
                }
                else
                {
                    len += 2;
                }
            }
            else
            {
                len += 1;
            }

            memset(buf, 0, len*sizeof(int));
            buf[0] = buf[len-1] = 1;
            num = totalNum - 2;
            mid = len/2;

            if (len & 1)
            {
                begin = end = mid;
                buf[mid] = num;
                num = 0;

                arrangeMidOfOddArray(buf, begin, end, mid, num);
            }
            else
            {
                begin = mid - 1;
                end = begin + 1;
            }

            spreadFromMiddle(num, buf, begin, end);
            success = true;
        }

        if (success)
        {
            outputString(buf, output, len);
            string result(output);

            delete []buf;
            delete []output;
            return result;
        }
        else
        {
            return "Impossible";
        }
    } 
};

//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{ 
    cout<<Test::palindrom("131")<<endl; 
} 
//end //提示:自动阅卷结束唯一标识,请勿删除或增加


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值