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() << ‘\n‘;
			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\n", ans[i].first, ans[i].second);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/yyf0309/p/12219186.html

时间: 2024-08-30 14:39:14

loj 3217 「PA 2019」Desant - 动态规划 - 复杂度分析的相关文章

loj #3146. 「APIO 2019」路灯

loj #3146. 「APIO 2019」路灯 暴力的话就是查询\((l,r)\)之间是否全部是1,考虑如何优化查询 我们可以利用\(set\)来维护每一个全\(1\)区间和它出现的时间,具体的,用\((lp,rp,l,r)\)来表示\((lp,rp)\)的全\(1\)区间在时间\([l,r]\)中是存在的 那么对于一个在时间\(i\)的询问\((l_i,r_i)\),\((lp,rp,l,r)\)会对它产生贡献当且仅当\(lp\leq l_i,rp\geq r_i,i\geq l\),产生的

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

loj #3144. 「APIO 2019」奇怪装置 很明显的是我们需要找到\((x,y)\)的循环节的长度 当\(t=0\)时,\(x=0,y=0\) 当\(t\neq 0\)时,仍然要使的\(x=0,y=0\)的话,必有 \[ \begin{cases} t+\lfloor \frac{t}{B} \rfloor \equiv0(mod\ A)\t\equiv0(mod\ B) \end{cases} \] 记\(t=t'B\),则有\(A|t'(B+1)\),故\(t'\)最小为\(\fr

Loj #3085. 「GXOI / GZOI2019」特技飞行

Loj #3085. 「GXOI / GZOI2019」特技飞行 题目描述 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代表着水平位置,纵坐标代表着飞行高度. 在最初的计划中,这 \(n\) 架飞机首先会飞行到起点 \(x = x_{st}\) 处,其中第 \(i\) 架飞机在起点处的高度为 \(y_{i,0}\).它们的目标是终点 \(x = x_{ed}\) 处,其中第 \(i\) 架飞机在终点处的高度应为 \(y

#3144. 「APIO 2019」奇怪装置

#3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个结论:该装置是一个特殊的时钟,它从过去的某个时间点开始测量经过的时刻数 \(t\),但该装置的创造者却将 \(t\) 用奇怪的方式显示出来.若从该装置开始测量到现在所经过的时刻数为 \(t\),装置会显示两个整数:\(x = ((t + \lfloor \frac{t}{B} \rfloor) \b

路灯「APIO 2019」

题意 有.复杂,自己上网搜 思路 \((x,y)\) 表示从\(x\)到\(y\)联通的时间长度. 那么查询操作相当于二维平面上的单点查询. 对于每一个\(i\),维护一个最左能到达的\(lm\),和最右能到达的\(rm\). 那么对于每一个更新操作,相当于对左上角为\((lm,i)\),右下角为\((i,rm)\)的矩形做修改. 于是就转换为类似「简单题」的题目了,可以CDQ分治解决,当然也可以直接上树套树. 代码 #include <bits/stdc++.h> using namespa

loj 3014「JOI 2019 Final」独特的城市

loj 我本来是直接口胡了一个意思一样的做法的,但是因为觉得有点假+实现要用并查集(?)就卡了好一会儿... 对于一个点\(x\)来说,独特的点一定在它的最长链上,如果有独特的点不在最长链上,那么最长链上一定有和他到\(x\)距离相同的点,矛盾 然后对于一个点,最长链端点一定可以是直径的两端点之一,所以如果我们分别以树的直径的两端点为根进行dfs,那么一个点在其中一次dfs中,独特的点都会在到根的路径上,所以我们用栈维护到根的点,然后不同颜色数开桶来维护,每次压栈或弹栈时改变桶内元素个数,然后根

「51单片机」RS232串口通信代码分析

想来想去不知道要怎么样把232串口通信说清楚,想想还是直接把代码分析一遍吧... 重点是“常用波特率与定时器1的参数关系”这张表格!波特率的设置很重要! 一.串口初始化 void usart_init() { SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1 TMOD = 0x20; //定时器工作方式2 PCON = 0x00; TH1 = 0xFD; //波特率9600.数据位8.停止位1.效验位无 (11.0592M) TL1 = 0xFD; ES = 1; //开

[LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主

[LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主 试题描述 "A fight? Count me in!" 要打架了,算我一个. "Everyone, get in here!" 所有人,都过来! 小Y是一个喜欢玩游戏的OIer.一天,她正在玩一款游戏,要打一个Boss. 虽然这个Boss有 \(10^{100}\) 点生命值,但它只带了一个随从--一个只有 \(m\) 点生命值的"恐怖的奴隶主". 这个"恐怖的奴隶主&qu

[LOJ#2328]「清华集训 2017」避难所

[LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所了." "唔,那你之后会去哪呢?" "去一个没有冬天的地方." 对于一个正整数 \(n\),我们定义他在 \(b\) 进制下,各个位上的数的乘积为 \(p = F(n, b)\). 比如 \(F(3338, 10) = 216\). 考虑这样一个问题,已知 \