题目大意:

你有$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 性质+动态规划的更多相关文章

  1. Codeforces 1070J Streets and Avenues in Berhattan dp

    Streets and Avenues in Berhattan 我们首先能发现在最优情况下最多只有一种颜色会分别在行和列, 因为你把式子写出来是个二次函数, 在两端取极值. 然后我们就枚举哪个颜色会 ...

  2. CF 1070J Streets and Avenues in Berhattan

    DP的数组f其实开得不够大,应该开200000,但是它在cf上就是过了... 题意是把一堆字母分别分配到行和列. 分析一下,答案实际上只和n行中和m列中每种字母分配的个数有关.而且答案只和" ...

  3. 2018-2019 ICPC, NEERC J. Streets and Avenues in Berhattan(DP)

    题目链接:https://codeforc.es/contest/1070/problem/J 题意:给出一个长度为 k 的字符串,选出 n 个和 m 个不同位置的字符构成两个字符串,使得两个字符串相 ...

  4. codeforces 447E or 446C 线段树 + fib性质或二次剩余性质

    CF446C题意: 给你一个数列\(a_i\),有两种操作:区间求和:\(\sum_{i=l}^{r}(a[i]+=fib[i-l+1])\).\(fib\)是斐波那契数列. 思路 (一) codef ...

  5. Codeforces 1383C - String Transformation 2(找性质+状压 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...

  6. Codeforces 1067E - Random Forest Rank(找性质+树形 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 一道不知道能不能算上自己 AC 的 D1E(?) 挺有意思的结论题,结论倒是自己猜出来了,可根本不会证( 开始搬运题解 ing: 碰到这样 ...

  7. Codeforces 809C - Find a car(找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 首先拿到这类题第一步肯定要分析题目给出的矩阵有什么性质.稍微打个表即可发现题目要求的矩形是一个分形.形式化地说,该矩形可以通过以下方式生成 ...

  8. Codeforces Round #382 (Div. 2)C. Tennis Championship 动态规划

    C. Tennis Championship 题目链接 http://codeforces.com/contest/735/problem/C 题面 Famous Brazil city Rio de ...

  9. Codeforces 822D My pretty girl Noora - 线性筛 - 动态规划

    In Pavlopolis University where Noora studies it was decided to hold beauty contest "Miss Pavlop ...

随机推荐

  1. C# XML序列化和反序列化

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  2. 【译】第九篇 Integration Services:控制流任务错误

    本篇文章是Integration Services系列的第九篇,详细内容请参考原文. 简介在前面三篇文章,我们创建了一个新的SSIS包,学习了脚本任务和优先约束,并检查包的MaxConcurrentE ...

  3. 解决多个python的兼容问题

    方法1:将(安装路径和scripts)路径添加到系统环境变量,谁的顺序在前面谁就是默认的 方法2:修改python的名字,然后再终端输入比如python2或者python3

  4. App劫持病毒剖析:你的应用是如何被替换的(病毒防范方法)

    App劫持病毒剖析:你的应用是如何被替换的(病毒防范方法) 一.App劫持病毒介绍 App劫持是指执行流程被重定向,又可分为Activity劫持.安装劫持.流量劫持.函数执行劫持等.本文将对近期利用A ...

  5. Linux触摸屏驱动测试程序范例【转】

    转自:http://blog.sina.com.cn/s/blog_4b4b54da0102viyl.html 转载2015-05-09 16:28:27 标签:androiditlinux 触摸屏驱 ...

  6. aarch64_j1

    JSCookMenu-2.0.4-13.fc26.noarch.rpm 2017-02-14 07:06 37K fedora Mirroring Project Java-WebSocket-1.3 ...

  7. mysql优化【转】

    最近听讲了博森瑞老师的mysql优化公开课,这个是我整理的笔记. 现在说一下mysql的内存和I/O方面的两个特点. 一. mysql内存特点: 1.  也有全局内存和每个session的内存(每个s ...

  8. jQuery之字体大小的设置

    先获取字体大小,进行处理. 再将修改的值保存. slice() 方法可从已有的数组中返回选定的元素.arrayObject.slice(start,end).start     必需.规定从何处开始选 ...

  9. Maven 基础知识

    Maven MavenMaven 简介 Maven MavenMaven 是 Apache Apache Apache 软件基金会组织维护的 软件基金会组织维护的 软件基金会组织维护的 软件基金会组织 ...

  10. python基础学习之路No.3 控制流if,while,for

    在学习编程语言的过程中,有一个很重要的东西,它就是判断,也可以称为控制流. 一般有if.while.for三种 ⭐if语句 if语句可以有一个通俗的解释,如果.假如 如果条件1满足,则…… 如果条件2 ...