Codeforces1238E. Keyboard Purchase(状压dp + 计算贡献)
题目链接:传送门
思路:
题目中的m为20,而不是26,显然在疯狂暗示要用状压来做。
考虑状压字母集合。如果想要保存字母集合中的各字母的顺序,那就和经典的n!的状态的状压没什么区别了,时间复杂度为O(m22m),是不可行的,所以本题肯定有更好的做法。
考虑不保存字母集合中各字母的顺序。那么问题来了,新加入一个字母后,要如何计算这个新的字母对slowness产生的影响呢?
不妨设当前已经被选过的字母集合为i(0 ≤ i ≤ (1<<m)),当前要加入的字母j(0 ≤ j < m),且(i>>j&1) == 0。
考虑每次都把新的字母j放在i中的所有字母的右边,则字母j的加入对答案的影响为:
$\sum_{k\in i}cnt_{j,k}*(pos_{j}-pos_{k}) +\sum_{k\notin i}cnt_{j,k}*(pos_{k}-pos_{j}) $,其中$cnt_{j, k}$表示输入密码时,从j移动到k和从k移动到j的次数之和
其中,$pos_{j}$已知,为i中1的个数,但是pos_{k}因为没有记录i中各个字母的顺序,无法得知。
那么我们不妨只直接计算字母j对应的$pos_{j}$对答案产生的影响:$\sum_{k\in i}cnt_{j,k}*pos_{j}-\sum_{k\notin i}cnt_{j,k}*pos_{j}$
这样的做法还是O(m22m),但是预处理出这个东西$\sum_{k\in i}cnt_{j,k}*pos_{j}$,就可以把时间复杂度优化到O(m2m)了。
代码:O(m2m)
#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 20
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x) using namespace std;
typedef long long ll;
typedef double db; /** fast read **/
template <typename T>
inline void read(T &x) {
x = ; T fg = ; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -;
ch = getchar();
}
while (isdigit(ch)) x = x*+ch-'', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); } string s;
int f[mk(M)], cnt[mk(M)];
int main()
{
int n, m; read(n, m);
cin >> s;
for (int i = ; i < n; i++) {
int l = s[i-] - 'a', r = s[i] - 'a';
cnt[mk(l) | mk(r)]++;
}
for (int i = ; i < m; i++) {
for (int j = ; j < mk(m); j++) {
if (j & mk(i))
cnt[j] += cnt[j ^ mk(i)];
}
}
memset(f, 0x3f, sizeof f);
f[] = ;
for (int i = ; i < mk(m); i++) {
for (int j = ; j < m; j++) {
if ((i & mk(j)) == ) {
int add = n-;
add -= cnt[i ^ mk(j)] + cnt[mk(m)- - (i ^ mk(j))];
f[i ^ mk(j)] = min(f[i ^ mk(j)], f[i] + add);
}
}
}
cout << f[mk(m)-] << endl;
return ;
}
Codeforces1238E. Keyboard Purchase(状压dp + 计算贡献)的更多相关文章
- 【CF1238E】Keyboard Purchase(状压DP,贡献)
		题意:有m种小写字符,给定一个长为n的序列,定义编辑距离为序列中相邻两个字母位置差的绝对值之和,其中字母位置是一个1到m的排列 安排一种方案,求编辑距离最小 n<=1e5,m<=20 思路 ... 
- 【POJ 2923】Relocation(状压DP+DP)
		题意是给你n个物品,每次两辆车运,容量分别是c1,c2,求最少运送次数.好像不是很好想,我看了网上的题解才做出来.先用状压DP计算i状态下,第一辆可以运送的重量,用该状态的重量总和-第一辆可以运送的, ... 
- 【bzoj2734】集合选数(有点思维的状压dp)
		题目传送门:bzoj2734 这题一个月前看的时候没什么头绪.现在一看,其实超简单. 我们对于每个在$ [1,n] $范围内的,没有因数2和3的数$ d $,将它的倍数$ 2^a 3^b d $一起处 ... 
- HDU5816 Hearthstone(状压DP)
		题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collec ... 
- CF1103D Professional layer 状压DP
		传送门 首先对于所有数求gcd并求出这个gcd含有的质因子,那么在所有数中,只有这一些质因子会对答案产生影响,而且对于所有的数,每一个质因子只会在一个数中被删去. 质因子数量不会超过\(11\),所以 ... 
- Luogu4547 THUWC2017 随机二分图 概率、状压DP
		传送门 考虑如果只有$0$组边要怎么做.因为$N \leq 15$,考虑状压$DP$.设$f_i$表示当前的匹配情况为$i$时的概率($i$中$2^0$到$2^{N-1}$表示左半边的匹配情况,$2^ ... 
- NowCoder110E Pocky游戏 状压DP
		传送门 题意:给出$N$个数和一个长为$M$.所有数在$[1,N]$范围之内的正整数序列$a_i$,求出这$N$个数的一种排列$p_1...p_N$使得$\sum\limits_{i=2}^M |p_ ... 
- 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)
		洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ... 
- CCPC-Wannafly Winter Camp Day3 Div1 - 精简改良 - [生成树][状压DP]
		题目链接:https://zhixincode.com/contest/14/problem/D?problem_id=206 样例输入 1 5 5 1 2 1 1 3 1 2 4 1 2 5 1 ... 
随机推荐
- Dell做RAID配置图文全教程
			首先准备工作:Dell服务器 首先重启Dell,我们会看到Dell服务器的启动页面: 当我们看到出现下面这个界面的时候,根据提示按下Ctrl+R进到SAS磁盘阵列里面 备注:大多数Dell服务器进磁盘 ... 
- leetcode 137单词接龙
			直接层序遍历,结果有部分测试样例超时: class Solution { public: int ladderLength(string beginWord, string endWord, vect ... 
- [转]Tomcat中8005/8009/8080/8443端口的作用
			8005:关闭tomcat进程所用.当执行shutdown.sh关闭tomcat时就是连接8005端口执行“SHUTDOWN”命令--由此,我们直接telnet8005端口执行“SHUTDOWN”(要 ... 
- SweetAlert(弹出层插件)
			怀着非常.非常恼火的心情写下这个博文.我深深怀疑有一些人只会瞎粘贴复制别人的博文,自己试都不试就发布到网上,左右看的人想法,就此深通恶绝!! 废话不多说. SweetAlert是一个简洁好用的自制Al ... 
- Java学习之==>集合体系(待续。。)
			一.概述 Java的集合体系,本质上是一个陈放数据的容器,像之前学过的数组也是陈放数据的容器,但在 Java 中数组的长度是固定的,使用起来没那么方便.集合提供了更加强大的功能,使用起来也更方便和快捷 ... 
- Array数组对象
			1.数组方法: 1>字符串的连接: var myarr1= new Array("010") var myarr2= new Array("-",&quo ... 
- 深入浅出JavaScript(中文版)__莫里森  初读笔记
			创建变量,使用关键字var; 创建常量,使用关键字const; 大驼峰用于对象,小驼峰用于变量和函数. 在试图相加数字时意外做了字符串相连,是种常见的JavaScript错误.如果想做数字相加,请确定 ... 
- python学习之模块-模块(五)
			5.10 包 5.10.1 包的概念 [官网解释] Packages are a way of structuring Python's module namespace by using " ... 
- js脚本实现在该界面直接跳转到一个登录界面并且自动登录
			1:首先说明的是自动登录也是需要密码的,这是前一个网页传输过去的 2:这里我使用的是post提交表单的形式 <------------------------------------------ ... 
- python 一周总结
			从7月27前就开始了Djangoj框架的学习到今天一个项目实战已经过了一半了, django给我的感觉就像一个成熟的mov 首先是是数据模型层,Django已经成熟的加入了很多的数据模型供我们所使用 ... 
