BUAA 晴天小猪爱61

Limit

Time Limit : 2 s
Memory Limit : 131072 KB

Description

晴天小猪是一个正儿八经的人。他听说昂神大二就那么神了,真是太仰慕了。
<img:/richtext/res/484/QQ%E5%9B%BE%E7%89%8720131127214156.gif>
他听说昂神的id是Sd0061,所以他觉得含有61的的数字最喜欢了!
小猪觉得觉得,161,261,6199什么的最好了!
有一天晴天小猪发现一个不含有61的数,他非常伤心,感觉不会再爱了。但他相信,错的不是自己,是这个世界!于是,他决定对这些黑暗的数字进行拆分,拆成多个含61的数字的和。
晴天小猪希望拆这个数字,使得拆成的含61数字个数尽量少。他请你帮助他拆分,并输出这个方案,如果无论如何这个数字都拆不了,输出0。

Input

输入数据第一行为数据组数T,以下有T组数据。
每组数据为一个正整数n,代表要拆的数字。
输入数据满足n≤2,000,000,000。

数据一共有 2,000 组。

Output

对于每组数据输出最少拆成含61的数的个数,并给出任意一组方案。
如果无论如何这个数字都拆不了,输出0。

Sample Input

3
61
162
3879

Sample Output

1 61
0
2 1261 2618

Source

Liuyibo

题目思路:

这题可以转化为两种情况

当n>=6161时

该数一定可以分解成两个数形式分别是比如说为5位数

xxx61

61xx

只要满足 n = xxx61 + 61xx即可

当n<6100时

分析下可以形成的最少的形式为

x61x

xx61

以这种情况进行完全背包,用一个数组来记录能够产生该种情况的小于6100的数

再用完全背包,以它能够分解成的最小个数的状态记录下来。


详细看代码,16MS:

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define N 6100

vector<int> t;

struct node
{
	int flag;
	int geshu;
	int num;
	void clear()
	{
		flag = 0;
		geshu = 0;
		num = 0;
	}
}dp[N];

int in[N];
int T;
int vis[N];

void make()
{
	t.clear();
//	memset(vis,0,sizeof(vis));
//	memset(in,0,sizeof(in));
	in[0] = 1;
	memset(dp,0x3f,sizeof(dp));
	for(int i = 0 ; i <= 5 ; i ++ )
	{
		for(int j = 0 ; j <= 9 ; j ++ )
		{
			t.push_back( 1000*i + 610 + j );
	//		dp[1000*i+610+j].geshu = 1;
	//		in[1000*i+610+j] = 1;
			t.push_back( 1000*i + j*100 + 61 );
		//	in[1000*i + j * 100 + 61] =1;
	//		dp[1000*i+j*100 +61].geshu = 1;
		}
	}
	t.push_back( 6061 );
	//in[0] = 1;
	dp[0].geshu=0;
	for(int i = 0 ; i < t.size() ; i ++ )
	{
		for(int j = 0 ; j + t[i] < 6100 ; j ++ )
		{
			if( dp[t[i]+j].geshu > dp[j].geshu + 1 )
			{
				dp[t[i]+j].geshu = dp[j].geshu + 1;
				dp[t[i]+j].num = t[i];
				dp[t[i]+j].flag = j;
			}
		}
	}
	//for(int i = 0 ; i < 6100 ; i ++ )
	//{
	//	if( dp[i].geshu != 0x3f )
	//	{
	//		printf( "dp[%d].num = %d\n",i,dp[i].num);
	//	}
	//}
}

int fa[N];

int main()
{
	make();
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n;
		scanf("%d",&n);
		int t = 1;
		int flag = 0;
		int k = n;
		memset(fa,0,sizeof(fa));
		while( k )
		{
			fa[t] = k%10;
			k /= 10;
			if( fa[t] == 6 && fa[t - 1] == 1 )
			{
				flag = 1;
				break;
			}
			t ++;
		}

		if( flag )
		{
			printf("1 %d\n",n);
			continue;
		}

		if( n < 6100 )
		{
			if( dp[n].geshu > 10000 )
			{
				printf("0\n");
				continue;
			}
			printf("%d",dp[n].geshu);
			while(dp[n].geshu)
			{
				if( dp[n].geshu == 1 )
				{
					printf(" %d\n",n);
					break;
				}
				printf(" %d",dp[n].num);
				n = dp[n].flag;
			}
		}
		else
		{
			printf("2 ");
			int f = n;
			f %= 100;
			int f2 = n/100;
			f2 *= 100;
			int ans1;
			if( f < 61 )
			{
				f += 100;
				f2 -= 100;
			}
			ans1 = (f - 61) + 6100;
			int ans2 = 61 + (f2 - 6100);
			printf("%d %d\n",ans1,ans2);
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值