[hdu4713 Permutation]DP

题意:将一个数拆成若干数的和使得它们的最小公倍数最大

思路:一个数x可以拆成p1k1 + p2k2 + ... + pnkn形式,其中pi是质数或1。对于最小公倍数最大的情况,一定可以表示成这种形式。令dp[i][j]表示考虑前j个质数来构成i的最大公倍数,那么可以得到如下转移方程:

dp[i][j]=max{dp[i][j-1],dp[i-k][j-1]*k},k=prime[j]t<=i

用滚动数组计算dp数组,同时用一个数组来存具体方案,在dp值更新时更新具体方案。

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define copy(a, b)          memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 1e9 + 7;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

const int maxn = 1e4 + 7;

vector<int> prime;
vector<int> rst[maxn];
int extra[maxn];
bool vis[maxn];
double dp[maxn];

void getprimelist() {
    for (int i = 2; i < maxn; i ++) {
        if (!vis[i]) {
            prime.pb(i);
            for (ll j = (ll)i * i; j < maxn; j += i) {
                vis[j] = true;
            }
        }
    }
}

void initdp() {
    for (int i = 0; i < maxn; i ++) dp[i] = 1.0;
    for (int j = 0; j < prime.size(); j ++) {
        for (int i = maxn - 1; i; i --) {
            for (ll k = prime[j]; k <= i; k *= prime[j]) {
                if (umax(dp[i], dp[i - k] * k)) {
                    rst[i] = rst[i - k];
                    rst[i].pb(k);
                }
            }
        }
    }
    for (int i = 1; i < maxn; i ++) {
        sort(all(rst[i]));
        extra[i] = i;
        for (int j = 0; j < rst[i].size(); j ++) {
            extra[i] -= rst[i][j];
        }
    }
}

void work(int n) {
    vector<int> ans;
    for (int i = 0; i < extra[n]; i ++) ans.pb(1);
    for (int i = 0; i < rst[n].size(); i ++) ans.pb(rst[n][i]);
    int start = 1;
    for (int i = 0; i < ans.size(); i ++) {
        for (int j = start + 1; j < start + ans[i]; j ++) printf("%d ", j);
        printf("%d%c", start, i == ans.size() - 1? '\n' : ' ');
        start += ans[i];
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    getprimelist();
    initdp();
    int T, n;
    cin >> T;
    while (T --) {
        cin >> n;
        work(n);
    }
    return 0;
}
posted @ 2015-08-20 12:02  jklongint  阅读(159)  评论(0编辑  收藏  举报