csdn英雄会(pongo)题解之回文数

来源:互联网 发布:手机淘宝我要代理入口 编辑:程序博客网 时间:2024/05/21 10:34

题目描述:

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

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

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

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

例如:

输入919,输出14941

输入1,输出Impossible

解题思路:

题目的意思是给定一个1到10^1000次以内的正整数x,求大于x且是回文的最小y,并且x与y的各位数字之和相等。

回文数有如下性质:

(1)如果回文数各位之和是奇数,那么这个回文数的位数一定为奇数;

(2)设回文数的位数为w,当回文数的各位数字之和sum>=2时:

          当sum为偶数的话,这个回文数的位数w可以为大于等于k的任意数(k为sum/9对上取整);

          当sum为奇数的话,这个回文数的位数w可以为大于等于k的任意奇数(k为sum/9对上取整);

(3)给定各位之和sum 和 位数 w,且sum和w满足(2),那么我们可以求得各位之和为sum,位数为w的最小回文数和最大回文数,方法如下:

          最小回文数:由外向内枚举各位数字,枚举从小到大进行,注意最高位从1开始而不是从0开始枚举;

          最大回文数:由外向内枚举各位数字,枚举从大到小进行;

          复杂度为O(w)

通过上面的性质,得出下面的方法:

string palindrom (string   a){//返回值为所求的回文数sum为各位数字之和,w字符串a的长度即位数如果各位数字之和小于等于1,返回 Impossible;//一位数字单独处理if(w为1){if(sum为奇数)返回各位数字之和为sum,位数为3的最小回文;else if(sum为偶数)返回各位数字之和为sum,位数为2的最小回文;}//各位数字之和sum>=2,位数>=2if(sum为奇数){//和为奇数,那么所求的回文位数也得是奇数if(字符串a的位数w为偶数)返回 位数为字符串位数+1,各位数字之和为sum的最小回文;else if(字符串a位数w为奇数){if(字符串大于等于sum和w都相同的回文数的最大值)返回位数为字符串位数+2(确保位数是奇数),各位数字之和为sum的最小回文数;else通过getNear(sum,a,b)求得大于a的最小回文b}}else if(sum为偶数){//和为偶数if(字符串大于等于sum和w都相同的回文数的最大值)返回位数为字符串位数+1,各位数字之和为sum的最小回文;else通过getNear(sum,a,b)求得大于a的最小回文b}}

getNear(sum,a,b)描述:
根据字符串a的前半部分构造回文b的前半部分:
        如果恰好够造成的回文b的前半部分与a的前半部分一样:
                如果回文b的后半部分大于a的后半部分:
                        那么这个回文b即为所求;
                        例如:a=1234123 ,根据a的前半部分构造出来的b=1234321,那么b即为所求;
                如果回文b的后半部分小于等于a的后半部分:
                      那么需要找到以一个可+1的数位,然后对此位数字加1,然后内部数位重新够造成最小回文,得所求;
                        (由于是内部数字,所以这个内部最小回文的第一位可以是0);

                        第一个可+1数位为:本位数字<9,且内部数字之和大于等于2;
                        例如:a=1324312 ,根据a的前半部分构造出来的b=1324231,

                        由于b的后半部分小于a的后半部分, 那么在b中需要找到以一个可+1的数位,

                        第三位数字2满足条件,所以对其+1,然后内部数字够造成最小回文,结果b=1332331;

        如果构造成的回文b的前半部分中有个数字比a中对应数字大:
                那么,这个b即为所求;
                例如a=1234444,当在构造b的前半部分的第三位时,b=12___21, 如果第3个数字取3的话,
                那么剩余的内部数字之和为10,剩余内部位数为1,内部不能再继续构造,

                所以第三位取4>3,则b=1248421即为所求;
        如果构造成的回文b的前半部分中有个数字比a中对应数字小:
                那么,同样需要向前找到第一个可+1位,对其加1,然后内部够造成最小回文,得所求;
                例如:a=399212,当根据a的前半部分构造回文b的时候,第三位时:b=39__93,此时a的第三位是9,
                但是b剩余内部数字之和为2,所以最大是1<9,

                此时找到b的第一个可+1位为第一位,对其加1,然后内部够造成最小回文,那么b=409904

同样次过程的复杂度也是O(w),那么整个算法的复杂度是O(w)

代码见http://blog.csdn.net/xhu_eternalcc/article/details/18182639

码字画图不容易,有问题请评论,转载请标明出处。


0 0
原创粉丝点击