POJ 2011 - Primary X-Subfactor Series

http://poj.org/problem?id=2011

概要

ある数 n に対して,n の約数であり部分列でもある1以上の整数を subfactor という.

2, 13, 801, 882, 1324 はどれも 8013824 の部分列であるが,以下は部分列ではない.

n に対する x-subfactor series は n[1], ..., n[k] という整数の減少数列で,

を満たすものであり,x-subfactor は x-subfactor series の x 番目の数である.

例えば n = 2004 のとき,以下の2つの異なる x-subfactor series をもつ.

primary x-subfactor series は x-subfactor series の中で最も長いものである.もし複数存在する場合,2番目の数が最も小さいものを選び,もしそれも複数存在する場合は3番目の数が最も小さいものを…と選ぶことにする.

与えられた数の primary x-subfactor series を答える.

解法

メモ化しつつ,再帰的に primary x-subfactor series を計算する.

 1 #include <iostream>
 2 #include <vector>
 3 #include <map>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 map<int,pair<int,int> > cache;
 8 
 9 pair<int,int> solve(int start)
10 {
11   if (cache.count(start)) {
12     return cache[start];
13   }
14 
15   vector<int> v;
16   for (int i = start; i > 0; i /= 10) {
17     v.push_back(i % 10);
18   }
19   const int N = v.size();
20 
21   pair<int,int> ans = make_pair(0, -1);
22   for (int s = 1; s < (1<<N)-1; s++) {
23     int n = 0;
24     for (int i = 0; i < N; i++) {
25       if (s & (1<<i)) {
26         if (n == 0 && v[N-1-i] == 0) {
27           // leading zero
28           goto NEXT;
29         } else {
30           n = 10*n + v[N-1-i];
31         }
32       }
33     }
34     if (n > 1 && start % n == 0) {
35       int t = 0;
36       for (int i = 0; i < N; i++) {
37         if ((s & (1<<i)) == 0) {
38           t = 10*t + v[N-1-i];
39         }
40       }
41       const pair<int,int> r = solve(t);
42       if (ans.first < r.first+1 || (ans.first == r.first+1 && ans.second > t)) {
43         ans.first = r.first+1;
44         ans.second = t;
45         ans.second = t;
46       }
47     }
48 NEXT:
49     ;
50   }
51   cache[start] = ans;
52   return ans;
53 }
54 
55 int main()
56 {
57   int n;
58   while (cin >> n && n != 0) {
59     pair<int,int> ans = solve(n);
60     cout << n;
61     while (ans.second != -1) {
62       cout << ' ' << ans.second;
63       ans = cache[ans.second];
64     }
65     cout << endl;
66   }
67   return 0;
68 }
poj/2011.cc