Limit
Time Limit : 2 s
Memory Limit : 131072 KB
Description
晴天小猪是一个正儿八经的人。他听说昂神大二就那么神了,真是太仰慕了。
他听说昂神的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;
}