CodeForces 1070J Streets and Avenues in Berhattan 性质+动态规划
题目大意:
你有$k$个数,分为$26$种
对于每个数,你可以选择选进$A$集合或者$B$集合或者不选
要求$A$集合中必须有$n$个数,$B$集合中必须有$m$个数
记第$i$种数在$A$集合中的个数为$a_i$,$B$中个数为$b_i$
试最小代价$\sum a_i * b_i$
$k \leqslant 200000$,$n, m \leqslant 30000$
首先,我们打表得出一个结论,代价一定只由一种数得出
考虑证明:
我们不妨设代价由$A$得出,且集合$S_A$和$S_B$中分别有$i$个$A$和$a - i$个$A$
那么,如果我们尝试用$B$来替换$A$,不妨设从$B$中抽了$j$个$B$扔进$A$中,且一共有$b$个$B$
那么贡献差为$i * (a - i) - ((i - j) * (a - i + j) + j * (b - j))(0 \leq j \leq min(i, b))$
化简后,为$2j^2 - j(2i - a+ b)$
这是一个开口向上的,以$j$为自变量的二次函数
最大值一定在端点取到,也就是$j = 0$或者$j = i$或者$j = b$取到
这三种情况对应着代价由$A$得出或者由$B$得出
我们可以枚举在中间的种类是哪一个
之后再枚举放在$A$中的数能取多少个
相应地我们可以知道最多可以放在$B$中多少个
可以通过背包来实现上述问题
由于实现不优,复杂度为$O(26^2 * (n+ m) + 26 * k)$
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
namespace remoon {
#define ri register int
#define tpr template <typename ra>
#define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
#define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)
#define gc getchar
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') p = p * + c - '', c = gc();
return p * w;
}
int wr[], rw;
#define pc(iw) putchar(iw)
tpr inline void write(ra o, char c = '\n') {
if(!o) pc('');
if(o < ) o = -o, pc('-');
while(o) wr[++ rw] = o % , o /= ;
while(rw) pc(wr[rw --] + '');
pc(c);
}
}
using namespace std;
using namespace remoon;
#define sid 30050
#define kid 200050 char s[kid];
bool f[kid];
int n, m, k, t, cnt[]; inline int judge() {
f[] = ;
memset(f, , sizeof(f));
rep(i, , ) drep(j, k, cnt[i])
f[j] |= f[j - cnt[i]];
rep(i, n, k - m)
if(f[i]) { puts(""); return ; }
return ;
} inline void solve() {
int ans = 1e9;
rep(i, , ) {
memset(f, , (n + m) << );
f[] = ;
rep(j, , ) if(i != j)
drep(v, n + m, cnt[j]) f[v] |= f[v - cnt[j]]; rep(j, , n + m)
if(f[j]) {
int l = max(n - j, );
int r = max(m - (k - cnt[i] - j), );
if(l + r <= cnt[i]) ans = min(ans, l * r);
}
}
write(ans);
} int main() {
t = read();
while(t --) {
n = read(); m = read(); k = read();
scanf("%s", s + );
int sn = strlen(s + );
memset(cnt, , sizeof(cnt));
rep(i, , sn) ++ cnt[s[i] - 'A'];
if(judge()) continue;
solve();
}
return ;
}
CodeForces 1070J Streets and Avenues in Berhattan 性质+动态规划的更多相关文章
- Codeforces 1070J Streets and Avenues in Berhattan dp
Streets and Avenues in Berhattan 我们首先能发现在最优情况下最多只有一种颜色会分别在行和列, 因为你把式子写出来是个二次函数, 在两端取极值. 然后我们就枚举哪个颜色会 ...
- CF 1070J Streets and Avenues in Berhattan
DP的数组f其实开得不够大,应该开200000,但是它在cf上就是过了... 题意是把一堆字母分别分配到行和列. 分析一下,答案实际上只和n行中和m列中每种字母分配的个数有关.而且答案只和" ...
- 2018-2019 ICPC, NEERC J. Streets and Avenues in Berhattan(DP)
题目链接:https://codeforc.es/contest/1070/problem/J 题意:给出一个长度为 k 的字符串,选出 n 个和 m 个不同位置的字符构成两个字符串,使得两个字符串相 ...
- codeforces 447E or 446C 线段树 + fib性质或二次剩余性质
CF446C题意: 给你一个数列\(a_i\),有两种操作:区间求和:\(\sum_{i=l}^{r}(a[i]+=fib[i-l+1])\).\(fib\)是斐波那契数列. 思路 (一) codef ...
- Codeforces 1383C - String Transformation 2(找性质+状压 dp)
Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...
- Codeforces 1067E - Random Forest Rank(找性质+树形 dp)
Codeforces 题面传送门 & 洛谷题面传送门 一道不知道能不能算上自己 AC 的 D1E(?) 挺有意思的结论题,结论倒是自己猜出来了,可根本不会证( 开始搬运题解 ing: 碰到这样 ...
- Codeforces 809C - Find a car(找性质)
Codeforces 题目传送门 & 洛谷题目传送门 首先拿到这类题第一步肯定要分析题目给出的矩阵有什么性质.稍微打个表即可发现题目要求的矩形是一个分形.形式化地说,该矩形可以通过以下方式生成 ...
- Codeforces Round #382 (Div. 2)C. Tennis Championship 动态规划
C. Tennis Championship 题目链接 http://codeforces.com/contest/735/problem/C 题面 Famous Brazil city Rio de ...
- Codeforces 822D My pretty girl Noora - 线性筛 - 动态规划
In Pavlopolis University where Noora studies it was decided to hold beauty contest "Miss Pavlop ...
随机推荐
- Sublime2编译Python程序EOFError:EOF when reading a line解决方法【转】
在Sublime2中编译运行Python文件时,如果代码中包含用户输入的函数时(eg. raw_input()),Ctrl+b编译运行之后会提示以下错误: 解决方法:安装SublimeREPL打开Su ...
- 【转】GridView 加载空行并点击编辑每一个单元格
代码 <script runat="server"> protectedvoid Button1_Click(object sender, System.EventAr ...
- 005_MAC下的VMware fushion快捷键(折中)
由于MAC和VMware Fushion虚拟机之间有一些快捷键的映射,所以Windows虚拟机就找了一个折中的方案.现总结MAC下的win常用快捷键==> <1>最小化窗口(Alt ...
- wordcount在本地运行报错解决:Exception in thread "main" java.lang.UnsatisfiedLinkError:org.apache.hadoop.io.native.NativeID$Windows.access
在windows中的intellij中运行wordcount程序,控制台输出以下报错 在Intellij编辑器中解决办法:本地重新创建NativeIO类,修改一个方法返回值,然后用新建的NativeI ...
- Flask:使用jsonify()转换为JSON的数据在Chrome显示为Unicode编码
Chrome 66,Flask 1.0.2,MongoDB 3.6.3, 创建了一个Flask应用,在将MongoDB中的数据使用PyMongo包获取后,再使用jsonify转换为JSON格式发送回请 ...
- KVM virsh常用命令篇
1.查看运行的虚拟机 virsh list 2.查看所有的虚拟机(关闭和运行的虚拟机) virsh list --all 3.连接虚拟机 virsh console +域名(虚拟机的名称) 4.退出虚 ...
- git —— bug分支
储藏工作现场 $ git stash 切换到需要修改bug的分支,创建临时分支 修复bug,修复完提交 修复完之后,切换到需要修改的分支.完成合并 合并后删除临时分支 完成后,可以重新回到没有修改完的 ...
- HDU 4597 Play Game(区间DP(记忆化搜索))
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 题目大意: 有两行卡片,每个卡片都有各自的权值. 两个人轮流取卡片,每次只能从任一行的左端或右端 ...
- SQL Server 管理常用的SQL和T-SQL
1. 查看数据库的版本 select @@version 常见的几种SQL SERVER打补丁后的版本号: 8.00.194 Microsoft SQL Server 2000 8.00.384 Mi ...
- Shell学习笔记:#*、%*字符串掐头去尾方法
一.语法 在shell中可以通过#.%对字符串进行掐头去尾操作,使用方法如下: # 表示掐头 % 表示去尾 单个#或%表示最小匹配 双个$或%表示最大匹配 二.例子1 假设我们定义一个变量为: fi ...