hdu 5920(高精度 + 模拟)

Ugly Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1592    Accepted Submission(s): 530
Special Judge


Problem Description
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 ( 1s101000 ).
 

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. en 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


题目意思:

给你一个大数 10^1000  然后让你把这个数字拆成五十个以内的回文数字

拆的方法很关键~~

这里提供一种思路 是这样的  先判断当前数字是不是回文数 如果是 就保存并退出循环  否则 设置两个伪指针 从中间向两边遍历 如果发现了不相同的数字 就记录此时的指针位置 然后把整个左边的数字翻转到右边 比如 123456 我第一次会把这个数字拆成 123321 当然 如果右边指针所指的数字较小的话 反过来之后还要给两个指针的点重新赋值  比如 124356  我会先记录下来 右边指针里的内容是3  然后把串变成124421然后 在把串变成123321 这样就好了 

还有一个很重要的问题是前导零  其实也没有很难判断  难在处理和细节 如果一个数字会出现前导零 比如100 或者 2000  这两种数字分别代表两种特殊的前导零情况 100这个数字 最佳情况是拆成99 + 1 但是 2000 就不能第一次拆成999   我们第一次会把它拆成 1991  所以前导零的情况还要看第一位是不是数字1  分情况~~


真的是恶心人~~

Devil is in the Details!!!

#include <iostream>
#include <cstdio>
#include <cstring>
#define debug()  puts("What the fuck ~~~");
using namespace std;
const int N = 1006;
string ans[100];
string sub(string a, string b)
{
	int i , j, k, s, flag = 1;
	int tmpa[10005], tmpb[10005], c[10005];
	string ans;
	if (a.size() < b.size() || (a.size() == b.size() && a.compare(b) < 0)) {
		string tmp = a;
		a = b;
		b = tmp;
		flag = 0;
	}
	while (a.length() > b.length())b = '0' + b;
	int len = a.length();
	for (i = 0; i <len; i ++) {
		tmpa[i] = a[i] - '0';
		tmpb[i] = b[i] - '0';
	}
	for (i = len - 1; i >= 0; i --) {
		if (tmpa[i] >= tmpb[i])
			c[i] = tmpa[i] - tmpb[i];
		else {
			c[i] = 10 + tmpa[i] - tmpb[i];
			tmpa[i - 1]--;
		}
	}
	for (i = 0; i < len - 1; i ++) {
		if (c[i] != 0)
			break;
	}
	for (j = i; j < len ; j ++)
		ans = ans + (char)(c[j] + '0');
	if(!flag)ans='-'+ans;
	return ans;
}
bool judge(string str)
{
	int len = str.length();
	int p, q;
	p = 0, q = len - 1;
	while (p < q) {
		if(str[p] != str[q])
			return false;
		p ++, q --;
	}
	return true;
}
int main()
{
	int  Case = 1;
	string str ,ss;
	int _;
	cin >> _;
	while (_ --) {
		int cnt = 0;
		cin >> str;
		while (true) {
			if(judge(str)) {
				if (str.length() != 1 || str[0] != '0') {
					ans[cnt ++] = str;
					break;
				}
			}
			int len_str = str.length();
			if(len_str & 1) {//      			如果长度是奇数的话~~
				string temp;
				temp.clear();
				int Left = len_str / 2 - 1;
				int Right = Left + 2;
				while(str[Left] == str[Right])Left--, Right++;
				//					考虑奇数并且有前导零部分~~
				if (Left == 0 && str[Right] == '0') {
					temp.clear();
					for (int i = 0; i < len_str - 1; i ++) 
                            temp += '9';
					if(str[0] != '1') {
                            temp.clear();
                            for (int i = 0; i < len_str; i ++) {
                                temp += (str[0] - 1);
                            }
					}
				}
				else {				//	奇数没有前导零部分
					temp.clear();
					char op = str[Right];
					int mid = len_str / 2;
					for (int i = 0; i <= mid; i ++)
						temp += str[i];
					int pos = mid - 1;
					while (pos != -1) temp += temp[pos--];
					if (str[Left] > str[Right]) {
						temp[Left] = temp[Right] = op;
					}
				}
				ans[cnt ++] = temp;
				str = sub(str , temp);
			}
			else {					//长度为偶数部分~~~
				string temp;
				int Left , Right;
				Left = len_str / 2 - 1;
				Right = Left + 1;
				while (str[Left] == str[Right])Left--, Right++;
				//				长度为偶数并且有前导零部分
				if (Left == 0 && str[Right] == '0') {
					temp.clear();
			                for (int i = 0; i < len_str - 1; i ++)
			                     temp += '9';
                       // cout << temp << endl;return 0;
					if(str[0] != '1') {
                            string test;
                            temp.clear();
                            for (int i = 0; i < len_str; i ++) 
                                temp += (str[0] - 1);
					}
				}
				else {			// 左边比右边小
					temp.clear();
					char op = str[Right];
					int mid = (len_str / 2) - 1;
					for (int i = 0; i <= mid ; i ++)
						temp += str[i];
					int pos = mid;
					while (pos != -1)temp += temp[pos--];
					if(str[Left] > str[Right]) 	//左边比右边大
						temp[Left] = temp[Right] = op;
				}
			//	cout << "temp == " << temp << endl;
				ans[cnt ++] = temp;
			//	cout << str << " - " << temp << " == " ;
				str = sub(str , temp);
		//		cout << str << endl;
			}
		}
		//cout << _ << endl;//continue;
		cout <<"Case #" << Case ++ << ":" << endl;
		cout << cnt << endl;
		for (int i = 0; i < cnt; i++) {
			cout << ans[i] << endl;
		}
	}
}
//21021215642310
//114451451201201204512078456210
//1111110000000000000000000001000110101010101010101010101010101010




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值