• 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;
    }
    

      

  • 相关阅读:
    专题一 Java基础语法
    IOC属于那种设计模式?
    java桌面应用开发
    Gitblit
    基于JSoup库的java爬虫开发学习——小步快跑
    tomcat和solr的整合——小步快跑
    SSM mapper文件SQL语句里面的 小于号 Tag name expected 无法识别解读
    Java从FTP服务器中获取PDF文件数据
    idea 控制台log日志中文乱码解决方案
    Java开发文档Swagger的使用详细教程
  • 原文地址:https://www.cnblogs.com/yyf0309/p/12219186.html
Copyright © 2020-2023  润新知