poj 2011

#include <iostream>
#include <cstdio>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>

#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int

using namespace std;

#define maxn 3005

int getnum(int *x, int len, int poi){
	int res = 0;
	for (int i = len - 1; i >= 0; i--)
		if (poi & (1 << i))
			res = res * 10 + x[i];
	
	return res;
}

bool head_zero(int *x, int len, int poi){
	for (int i = len - 1; i >= 0; i--)
		if (poi & (1 << i)){
			if (x[i] == 0) 
				return true;
			return false;
		}
	
	return true;
}

vector<int> vec[maxn];
int dp[maxn]; //表示val[num]后续最多还有多少个数字
int solve(int num){
	if (dp[num] != -1)
		return dp[num];  

	dp[num] = 0;
	int len = vec[num].size();

	for (int i = 0; i < len; i++)
		dp[num] = max(dp[num], solve(vec[num][i]));

	return ++dp[num];
}

vector<int> ans;
int val[maxn];
void dfs(int cur){
	ans.push_back(val[cur]);

	int len = vec[cur].size();
	if (len == 0) return;

	int minnum = INF, best = 0;
	for (int i = 0; i < len; i++){
		int v = vec[cur][i];
		if (dp[cur] == dp[v] + 1 && val[v] < minnum){
			minnum = val[v];
			best = v;
		}
	}
	dfs(best);
}

int main() {
	map <int, int> mp;

	int num;
	while (cin >> num,num){
		memset(dp, -1, sizeof dp);
		ans.clear();  
		mp.clear();

		for (int i = 0; i < 3000; i++) 
			vec[i].clear();

		if (num < 10){
			printf("%d\n", num);
			continue;
		}

		int beginnum = num;

		int x[10] = {};
		int n = 0;   //记录位数
		while (num > 0){
			x[n++] = num % 10;
			num /= 10;
		}

		int cnt = 0;
		for (int i = 1; i < (1 << n); i++){
			int u = getnum(x, n, i);  //取出x所有子序列
			if (!mp[u]){
				mp[u] = ++cnt;  //离散化,标记数字
				val[cnt] = u;
			}
		}

		for (int i = 1; i < (1 << n); i++)  {//遍历x所有的子集
			if (head_zero(x, n, i))
				continue;
			int u = getnum(x, n, i);  //取出该子集的数字
			for (int j = (i - 1)&i; j; j = (j - 1)&i) {//遍历u的所有子集
				if (head_zero(x, n, j)) 
					continue;

				int k = getnum(x, n, j);  //从u中取走的数字
				int v = getnum(x, n, i^j); //从u中取走数字后剩下的值

				if (k <= 1 || u % k)
					continue;   //如果u不能整除k,即k不是u的约数

				vec[mp[u]].push_back(mp[v]);  //vec[i]表示:当前数字为i的时候,接下来一个取值(满足约数+子串)可以为vec[i][j]
			}
		}

		for (int i = 1; i <= cnt; i++) 
			dp[i] = solve(i);

		dfs(mp[beginnum]);

		printf("%d", ans[0]);
		int len = ans.size();
		for (int i = 1; i < len; i++) 
			printf(" %d", ans[i]);
		printf("\n");
	}

	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值