HDU - 5920 Ugly Problem(Java大数+贪心)

题目链接:点击查看

题目大意:给出一个非常大的数字 n (\small 10^{1000}),现在要求将其拆分为数量不超过 50 个的回文串之和

题目分析:贪心去分就好了,贪心策略如下,奇偶两种情况:对于奇串 12345:

  1. 选择前半段 123
  2. 将其减一,变为 122
  3. 构造回文串 12221
  4. 用原数字减去当前回文串然后继续操作

对于偶串 123456:

  1. 选择前半段 123
  2. 将其减一,变为 122
  3. 构造回文串 122221
  4. 用原数字减去当前回文串然后继续操作

这样就好了,因为每次选择了前半段,所以每次数字的长度都会减少一半,那么 \small 10^{1000} 所需要的操作次数也是 log(1000) 次就够了

选出的前半段需要减一,是为了保证构造出来的回文串一定比原数字要小,如果数字是 321 的话,选出前半段 32 直接构造成 323 的话,会比原数字还要大,但如果减一构造出 313 的话,就能保证一定比原数字要小了

最后当数字小于 20 的时候需要特判一下,不然会陷入死循环

  1. 0 无需处理
  2. 1 ~ 9 保持原数字
  3. 10 拆为 1 和 9
  4. 11 ~ 20 拆为 11 + x ,x < 10

剩下的用 java 模拟就好了,因为需要大数和字符串之间频繁的转换,用 C++ 的话会比较繁琐

代码:

import java.math.BigInteger;
import java.util.Scanner;

class Main 
{
	static Scanner cin = new Scanner(System.in);
    public static void main(String []args) 
	{
		int kase=cin.nextInt();
		BigInteger _20=BigInteger.valueOf(20);
		for(int t=1;t<=kase;t++)
		{
		    String ans[]=new String[60];
		    int cnt=0;
		    BigInteger n=cin.nextBigInteger();
		    while(n.compareTo(_20)>=1)//n>=20
		    {
		        String res;
		        String s=n.toString();
		        int len=s.length();
		        String s1=s.substring(0,(len+1)/2);
		        BigInteger temp=new BigInteger(s1);
		        temp=temp.subtract(BigInteger.ONE);//减一
		        s1=temp.toString();
		        if((len&1)==0)//偶数串
		        {
		            StringBuffer s2=new StringBuffer(s1);
		            s2.reverse();
		            res=s1+s2.toString();
		        }
		        else//奇数串
		        {
		            StringBuffer s2=new StringBuffer(s1.substring(0,len/2));
		            s2.reverse();
		            res=s1+s2.toString();
		        }
		        ans[++cnt]=res;
		        BigInteger num=new BigInteger(res);
		        n=n.subtract(num);
		    }
		    int num=n.intValue();
		    if(num>=11)//[11,20]
		    {
		        num-=11;
		        ans[++cnt]=String.valueOf(11);
		    }
		    if(num==10)//特判10
		    {
		        num-=9;
		        ans[++cnt]=String.valueOf(9);
		    }
		    if(num!=0)
		    {
		        ans[++cnt]=String.valueOf(num);
		    }
			System.out.printf("Case #%d:\n%d\n",t,cnt);
			for(int i=1;i<=cnt;i++)
			    System.out.println(ans[i]);
		}
    }
}

 

你可能感兴趣的:(高精度运算,贪心)