字符串与大数处理之”Ugly Problem“

本文介绍了一种解决特定数学问题的算法,即将一个大整数(最多1000位)分解为若干个回文数之和,总数不超过50个。通过取字符串前半部分,减一,翻转,进行大数减法,循环直至小于20,并对小于20的情况进行特殊处理。使用Java的BigInteger类和StringBuffer类实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 (1s10^1000).

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. Then 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

 

题目大意:给你一个不超过1000位的整数,将其分解成若干个回文数,总数不超过50个。

解题思路:取字符串的前一半,减一,翻转过去,大数减小数,循环上述过程直到小于20。

     小于20的时候进行特判

                 12到19拆成  11 + x

                 11不动

                 10拆成     1 + 9

                 小于10不动

     注意不要把”0“算进去

     等于20的情况不需要特判,因为20还在while里面继续循环成11+9,然后9这个数才会从while里出来。

     如: 9657932  取9657  变成9656  翻转为9656569  再用9657932-9656569  循环下去即可

AC代码:

 1 import java.util.*;
 2 import java.lang.Math;
 3 import java.math.BigInteger; 
 4 public class Main{
 5     public static void main(String[] args){
 6         Scanner sc = new Scanner(System.in);
 7         int t = sc.nextInt();
 8         String enter = sc.nextLine();
 9         BigInteger one = new BigInteger("1");
10         BigInteger zero = new BigInteger("0");
11         BigInteger twenty = new BigInteger("20");
12         int k = 1;
13         while(t > 0){
14             String in = sc.nextLine();
15             int sum = 0;
16             String out[] = new String[50];
17             int index = 0;int flag = 0;
18             BigInteger inn = new BigInteger(in);
19             while((inn.subtract(twenty)).compareTo(zero) != -1){
20                 if(in.length() % 2 == 1){
21                     int l = in.length();
22                     String sub = in.substring(0,l/2 + 1);
23                     
24                     BigInteger bi = new BigInteger(sub);
25                     bi = bi.subtract(one);
26                     if((String.valueOf(bi)).length() != (l/2)+1){flag = 1;}
27                     
28                     StringBuffer b1 = new StringBuffer(String.valueOf(bi));
29                     StringBuffer b2 = new StringBuffer(String.valueOf(bi));
30                     if(flag == 0){b2.deleteCharAt(l/2);flag = 0;}
31                                         
32                     b1 = b1.append(b2.reverse());
33                     out[index] = String.valueOf(b1);index ++;sum ++;
34                     
35                     BigInteger tt = new BigInteger(String.valueOf(b1));
36                     inn = inn.subtract(tt);
37                     in = String.valueOf(inn);
38                     
39                 }
40                 else{
41                     int l = in.length();
42                     String sub = in.substring(0,l/2);
43                     
44                     BigInteger bi = new BigInteger(sub);
45                     bi = bi.subtract(one);
46                     StringBuffer b1 = new StringBuffer(String.valueOf(bi));
47                     StringBuffer b2 = new StringBuffer(String.valueOf(bi));
48                     b1 = b1.append(b2.reverse());
49                     out[index] = String.valueOf(b1);index ++;sum ++;
50                     
51                     BigInteger tt = new BigInteger(String.valueOf(b1));
52                     inn = inn.subtract(tt);
53                     in = String.valueOf(inn);
54                     
55                 }    
56             }
57             int last = Integer.valueOf(in);
58             if(last <= 19 && last >= 12){
59                 out[index] = "11";index ++;
60                 int te = last - Integer.valueOf("11");
61                 out[index] = String.valueOf(te);index ++;
62                 sum = sum + 2;
63             }
64             else if(last == 11){out[index] = "11";index ++;sum ++;}
65             else if(last == 10){out[index] = "9";index ++;out[index] = "1";index ++;sum = sum + 2;}
66             else if(last >= 1 && last <= 9){out[index] = String.valueOf(last);index ++;sum ++;}
67             System.out.println("Case #" + k + ":");System.out.println(sum);
68             for(int i = 0;i < index;i ++){
69                 System.out.println(out[i]);
70             }
71             k ++;t --;
72         }
73     }
74 }

一开始将题意理解为有10^1000那么长的字符串,以为用不了substring();浪费了好长时间。。。

奇数的if里面有个flag,是判断是不是取半后出现了10000-1=9999类似的情况,有的话就出大问题了。

偶数就没有这种问题,我试了下,1000 = 898 + 3 + 99,就不会是 999 + 1。。。

当然可以加上flag,却会更麻烦,因为偶数长度变成了奇数长度,还得删去一个字符再反转,所以没有加flag判断。。。

 

 

下面稍作讲解java大整数类(BigInteger类)以及StringBuffer在本题中出现的方法

    BigInteger类:要使用  import java.math.BigInteger; 

      声明:大整数类不能像int型声明并赋初值(int i = 1;),要使用  BigInteger x = new BigInteger(str);  这种方法。

      比较:大整数类也不能用符号比较,只能用类似比较字符串的方法来比较,如出现在19行的  while((inn.subtract(twenty)).compareTo(zero) != -1)

         if(a.compareTo(b) == -1)   => a < b
         if(a.compareTo(b) == 0)    => a == b
         if(a.compareTo(b) == 1)    => a > b

      运算:

         a.add(b)       大整数加法

         a.subtract(b)     大整数减法

         a.multiply(b)      大整数乘法

         a.divide(b)      大整数除法(取整)

         a.remainder(b)    大整数取模

    StringBuffer类:

      声明:和大整数类有些相似,在括号里放入初值  StringBuffer x = new StringBuffer(str);  但是StringBuffer无法使用‘+’这种运算符运算。

      字符串反转:    x.reverse();  

      字符串追加:    x.append(str);

      按索引删除字符:  x.deleteCharAt(index);

    要注意的是,这些StringBuffer的方法都会返回到本身,因此语句执行后,这个字符串就会改变。

    我们用一个小的示例程序来说明:

 1 import java.util.*;
 2 
 3 public class Main{
 4     public static void main(String[] args){
 5         String str1 = "aaabbb";
 6         String str2 = str1 + "ccc";
 7         System.out.println("str1: " + str1);
 8         System.out.println("str2: " + str2);
 9         StringBuffer stb1 = new StringBuffer(str1);
10         StringBuffer stb2 = new StringBuffer(str1);
11         StringBuffer stb3 = new StringBuffer(str1);
12         stb2 = stb2.append(stb1.reverse());
13         System.out.println("stb1: " + stb1);
14         System.out.println("stb2: " + stb2);
15         stb3 = stb3.append(stb1.deleteCharAt(2));
16         System.out.println("stb1: " + stb1);
17         System.out.println("stb2: " + stb2);
18         System.out.println("stb3: " + stb3);
19     }
20 }
21 
22 //output
23 
24 //str1: aaabbb
25 //str2: aaabbbccc
26 
27 //stb1: bbbaaa
28 //stb2: aaabbbbbbaaa
29 
30 //stb1: bbaaa
31 //stb2: aaabbbbbbaaa
32 //stb3: aaabbbbbaaa

    从示例中我们可以看出,进行操作后str1没有改动,但是stb1却一直发生变化。

 

转载于:https://www.cnblogs.com/love-fromAtoZ/p/7353536.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值