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 ...
随机推荐
- leetcode-easy-string-387 First Unique Character in a String
mycode 24.42% class Solution: def firstUniqChar(self, s: str) -> int: dic = {} for i in range(le ...
- Oracle9i的详细安装与卸载步骤(有图解)
Oracle9i的安装和卸载详解 本章将以Windows操作系统为例讲述Oracle9i数据库的安装 ...
- DAY 3模拟赛
DAY3 钟皓曦来了! T1 网址压缩 [问题描述] 你是能看到第一题的 friends 呢. ——hja 众所周知,小葱同学擅长计算,尤其擅长计算组合数,但这个题和组合数没什么关 ...
- OpenCV学习笔记(11)——Canny边缘检测
了解Canny边缘检测的概念 1.原理 Canny边缘检测是一种非常流行的边缘检测算法,是 John F.Canny在1986年提出的.它是一个有很多步构成的算法 1)噪声去除 使用5*5的高斯滤波器 ...
- leetcode 347前k个高频元素
通过hash map遍历一遍存储出现的次数,通过小顶堆存储k个元素 //设想利用hash map来存储每个元素的个数:采用小顶堆存储k个元素:timeO(n+klogk)spaceO(n+k) cla ...
- redhat下配置SEED DVS6446开发环境3
1.运行arm_v5t_le-gcc,报错为: 64bit的Linux操作系统,无法运行32bit的应用程序 /lib/ld-linux.so.2: bad ELF interpreter: No s ...
- JavaWeb实现文件上传下载功能实例解析 (好用)
转: JavaWeb实现文件上传下载功能实例解析 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web ...
- Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)
示例代码如下: package com.miracle.luna.lambda; import java.util.HashMap; import java.util.Iterator; import ...
- 使用IDEA工具创建本地项目并且上传到码云
需要条件: 1.码云/Github建好的git项目 2.IDEA编辑器 3.本地项目 步骤1:创建远程项目 步骤2:复制远程项目地址 注意:此处码云官方已经给出上传项目方法,不过用的是命令行的形式, ...
- 简单的servlet下载
<servlet> <servlet-name>servletTest</servlet-name> <servlet-class>com.shangs ...