loj 3217 「PA 2019」Desant - 动态规划 - 复杂度分析

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj 3217 「PA 2019」Desant - 动态规划 - 复杂度分析相关的知识,希望对你有一定的参考价值。

题目传送门

  传送门

  一个非常显然的想法是记录后面的值相邻两个之间在前面选了多少个数。

  众所周知(比如我就不知道,我甚至以为它非常大),若干个和为 $n$ 的数的乘积最大为 $O(3^{n/3})$,最优方案是拆成若干个 3 和常数个 2。

  然后 dp 即可。

  时间复杂度 $O(n^23^{frac{n + 1}{3}})$.

Code

#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

const int N = 41;
const int inf = (signed) (~0u >> 2);

#define pii pair<int, long long>

pii operator + (pii a, pii b) {
	if (a.first == b.first)
		return pii(a.first, a.second + b.second);
	return min(a, b);
}

int n;
int p[N];

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", p + i);
		--p[i];
	}
	vector<boolean> have (n, true);
	vector<int> lenc (n + 1, 1), lenp;
	vector<int> prodc (n + 2, 1), prodp;
	vector<pii> f {pii(0, 1)}, g;
	vector<int> vs;
	for (int i = 1; i <= n; i++) {
		swap(lenp, lenc);
		swap(prodp, prodc);
		swap(f, g);
		int id = 0;
		for (int j = 0; j < p[i]; j++)
			id += have[j];
		have[p[i]] = false;
		lenc.clear();
		prodc = {1};
		int ls = -1;
		for (int j = 0; j < n; j++) {
			if (have[j]) {
				lenc.push_back(j - ls);
				prodc.push_back(prodc.back() * lenc.back());
				ls = j;
			}
		}
		lenc.push_back(n - ls);
		prodc.push_back(prodc.back() * lenc.back());
		f = vector<pii>(prodc.back(), pii(inf, 0));
		for (int s = 0; s < prodp.back(); s++) {
			if (g[s].first == inf)
				continue;
			vs.clear();
			int t = s;
			for (auto l : lenp)
				vs.push_back(t % l), t /= l;
			int dlt = 0;
			for (int j = id + 1; j < (signed) vs.size(); j++)
				dlt += vs[j];
			vs[id] += vs[id + 1];
//			cerr << id << " " << vs.size() << ‘
‘;
			vs.erase(vs.begin() + id + 1);
			int ns = 0;
			for (int j = 0; j < (signed) lenc.size(); j++)
				ns += vs[j] * prodc[j];
			f[ns] = f[ns] + g[s];
			g[s].first += dlt;
			ns += prodc[id];
			f[ns] = f[ns] + g[s];
		}
	}
	vector<pii> ans (n + 1, pii(inf, 0)); 
	for (int s = 0; s < prodc.back(); s++) {
		if (f[s].first == inf)
			continue;
		vs.clear();
		int t = s, len = 0;
		for (auto l : lenc)
			len += t % l, t /= l;
		ans[len] = ans[len] + f[s];
	}
	for (int i = 1; i <= n; i++) {
		printf("%d %lld
", ans[i].first, ans[i].second);
	}
	return 0;
}

  

以上是关于loj 3217 「PA 2019」Desant - 动态规划 - 复杂度分析的主要内容,如果未能解决你的问题,请参考以下文章

loj2073 「JSOI2016」扭动的回文串

Loj#6433「PKUSC2018」最大前缀和(状态压缩DP)

loj 3236 [POI2019 R1] Uk?ad scalony

Loj #3111. 「SDOI2019」染色

loj #3144. 「APIO 2019」奇怪装置

loj #3146. 「APIO 2019」路灯