題目鏈接:點擊查看
題目大意:給出一個非常大的數字 n (),現在要求將其拆分爲數量不超過 50 個的迴文串之和
題目分析:貪心去分就好了,貪心策略如下,奇偶兩種情況:對於奇串 12345:
- 選擇前半段 123
- 將其減一,變爲 122
- 構造迴文串 12221
- 用原數字減去當前迴文串然後繼續操作
對於偶串 123456:
- 選擇前半段 123
- 將其減一,變爲 122
- 構造迴文串 122221
- 用原數字減去當前迴文串然後繼續操作
這樣就好了,因爲每次選擇了前半段,所以每次數字的長度都會減少一半,那麼 所需要的操作次數也是 log(1000) 次就夠了
選出的前半段需要減一,是爲了保證構造出來的迴文串一定比原數字要小,如果數字是 321 的話,選出前半段 32 直接構造成 323 的話,會比原數字還要大,但如果減一構造出 313 的話,就能保證一定比原數字要小了
最後當數字小於 20 的時候需要特判一下,不然會陷入死循環
- 0 無需處理
- 1 ~ 9 保持原數字
- 10 拆爲 1 和 9
- 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]);
}
}
}