题目传送门:LOJ #3089

题意简述:

有一个长度为 \(n\) 的母串,其中某些位置已固定,另一些位置可以任意填。

同时给定 \(m\) 个小串,第 \(i\) 个为 \(S_i\),所有位置都已固定,它的价值为 \(V_i\)。

每次每个小串在母串中出现一次,便会给答案的多重集贡献一个 \(V_i\)。

最终的答案为多重集的几何平均数,定义空集的几何平均数为 \(1\)。

请你求出一个合法母串(往可以填的位置填合法字符)使得答案最大。

\(1\le n,s\le 1501\),\(1\le V_i\le \max V=10^9\),其中 \(\displaystyle s=\sum_{i=1}^{m}|S_i|\)。

题解:

假设多重集的大小为 \(c\),第 \(i\) 个元素为 \(w_i\),则 \(\displaystyle\mathrm{Ans}=\sqrt[c]{\prod_{i=1}^{c}w_i}\)。

两边取对数,有 \(\displaystyle\ln\mathrm{Ans}=\frac{1}{c}\sum_{i=1}^{c}\ln w_i\),转化为经典的 0/1 分数规划问题。

二分答案,若等式右边大于 \(\mathrm{mid}\),则有:

\(\begin{aligned}\frac{1}{c}\sum_{i=1}^{c}\ln w_i&>\mathrm{mid}\\\sum_{i=1}^{c}\ln w_i&>c\cdot\mathrm{mid}\\\sum_{i=1}^{c}(\ln w_i-\mathrm{mid})&>0\end{aligned}\)

所以,建出小串的 AC 自动机,然后二分答案后在 AC 自动机上 DP 判断不等式是否满足。

DP 时每个小串的权值设为 \(\ln V_i-\mathrm{mid}\),注意要记录最佳转移点,以输出方案。

下面是代码,复杂度 \(\mathcal{O}(s\Sigma(\log\max V-\log\epsilon))\):

#include <cstdio>
#include <cmath> typedef double f64;
const int MN = 1505, Sig = 10;
const f64 eps = 1e-6, inf = 1e99; int N, M;
char T[MN]; char str[MN];
int ch[MN][Sig], fail[MN], sum[MN], cnt;
f64 val[MN]; inline void Insert(char *s, f64 v) {
int now = 0;
for (; *s; ++s) {
if (!ch[now][*s & 15]) ch[now][*s & 15] = ++cnt;
now = ch[now][*s & 15];
} ++sum[now], val[now] += v;
} int que[MN], l, r;
void BuildAC() {
fail[0] = -1;
que[l = r = 1] = 0;
while (l <= r) {
int u = que[l++];
for (int i = 0; i < Sig; ++i) {
if (ch[u][i]) {
int x = fail[u];
while (~x && !ch[x][i]) x = fail[x];
if (~x) fail[ch[u][i]] = ch[x][i];
que[++r] = ch[u][i];
}
else if (~fail[u]) ch[u][i] = ch[fail[u]][i];
}
}
for (int i = 2; i <= r; ++i)
sum[que[i]] += sum[fail[que[i]]],
val[que[i]] += val[fail[que[i]]];
} f64 f[MN][MN];
int g[MN][MN][2];
char AT[MN];
inline f64 DP(f64 V) {
for (int j = 0; j <= cnt; ++j) val[j] -= sum[j] * V;
for (int i = 0; i <= N; ++i)
for (int j = 0; j <= cnt; ++j)
f[i][j] = -inf;
f[0][0] = 0;
for (int i = 0; i < N; ++i) {
for (int j = 0; j <= cnt; ++j) {
if (f[i][j] == -inf) continue;
if (T[i] == '.') {
for (int k = 0; k < Sig; ++k) {
int _j = ch[j][k];
if (f[i + 1][_j] < f[i][j] + val[_j])
f[i + 1][_j] = f[i][j] + val[_j],
g[i + 1][_j][0] = j,
g[i + 1][_j][1] = k;
}
}
else {
int _j = ch[j][T[i] & 15];
if (f[i + 1][_j] < f[i][j] + val[_j])
f[i + 1][_j] = f[i][j] + val[_j],
g[i + 1][_j][0] = j,
g[i + 1][_j][1] = T[i] & 15;
}
}
}
for (int j = 0; j <= cnt; ++j) val[j] += sum[j] * V;
int ans = 0;
for (int j = 1; j <= cnt; ++j)
if (f[N][j] > f[N][ans]) ans = j;
for (int i = N, j = ans; i >= 1; --i)
AT[i - 1] = g[i][j][1] | 48,
j = g[i][j][0];
return f[N][ans];
} int main() {
scanf("%d%d", &N, &M);
scanf("%s", T);
for (int i = 1; i <= M; ++i) {
f64 v;
scanf("%s%lf", str, &v);
Insert(str, log(v));
}
BuildAC();
f64 l = 0, r = log(1e9 + 5), mid, ans = 0;
while (r - l > eps) {
mid = (l + r) / 2;
if (DP(mid) > 0) ans = mid, l = mid;
else r = mid;
}
DP(ans);
printf("%s\n", AT);
return 0;
}

LOJ 3089: 洛谷 P5319: 「BJOI2019」奥术神杖的更多相关文章

  1. LOJ 3093: 洛谷 P5323: 「BJOI2019」光线

    题目传送门:LOJ #3093. 题意简述: 有 \(n\) 面玻璃,第 \(i\) 面的透光率为 \(a\),反射率为 \(b\). 问把这 \(n\) 面玻璃按顺序叠在一起后,\(n\) 层玻璃的 ...

  2. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  3. 【LOJ】#3089. 「BJOI2019」奥术神杖

    LOJ#3089. 「BJOI2019」奥术神杖 看见乘积就取log,开根号就是除法,很容易发现这就是一道01分数规划.. 然后建出AC自动机直接dp就行,判断条件要设成>0,因为起点的值是1, ...

  4. LOJ 3089 「BJOI2019」奥术神杖——AC自动机DP+0/1分数规划

    题目:https://loj.ac/problem/3089 没想到把根号之类的求对数变成算数平均值.写了个只能得15分的暴力. #include<cstdio> #include< ...

  5. LOJ 3045: 洛谷 P5326: 「ZJOI2019」开关

    题目传送门:LOJ #3045. 题意简述 略. 题解 从高斯消元出发好像需要一些集合幂级数的知识,就不从这个角度思考了. 令 \(\displaystyle \dot p = \sum_{i = 1 ...

  6. LOJ 3043: 洛谷 P5280: 「ZJOI2019」线段树

    题目传送门:LOJ #3043. 题意简述: 你需要模拟线段树的懒标记过程. 初始时有一棵什么标记都没有的 \(n\) 阶线段树. 每次修改会把当前所有的线段树复制一份,然后对于这些线段树实行一次区间 ...

  7. LOJ 2483: 洛谷 P4655: 「CEOI2017」Building Bridges

    题目传送门:LOJ #2483. 题意简述: 有 \(n\) 个数,每个数有高度 \(h_i\) 和价格 \(w_i\) 两个属性. 你可以花费 \(w_i\) 的代价移除第 \(i\) 个数(不能移 ...

  8. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  9. LOJ 2249: 洛谷 P2305: 「NOI2014」购票

    题目传送门:LOJ #2249. 题意简述: 有一棵以 \(1\) 号节点为根节点的带边权的树. 除了 \(1\) 号节点的所有节点上都有人需要坐车到达 \(1\) 号节点. 除了 \(1\) 号节点 ...

随机推荐

  1. 架构师成长之路6.6 DNS服务器搭建(构建企业级DNS)

    点击返回架构师成长之路 架构师成长之路6.6 DNS服务器搭建(构建企业级DNS) 采用LVS-DR模式负载均衡,多IDC,多套DNS集群,通过master-slave技术保证dns配置的一致性. 1 ...

  2. 【BZOJ3202】项链(莫比乌斯反演,Burnside引理)

    [BZOJ3202]项链(莫比乌斯反演,Burnside引理) 题面 BZOJ 洛谷 题解 首先读完题目,很明显的感觉就是,分成了两个部分计算. 首先计算本质不同的珠子个数,再计算本质不同的项链个数. ...

  3. __AFO

    博主已退役高考,博客基本就很少回复了 NOI2018的游记也没时间写了,以后补上吧[其实是自己懒] 嗯就这样,高三加油!

  4. Windows下禁用锁屏热键WinKey+L

    在注册表[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\System]中创建名字为DisableLockWo ...

  5. 在Vue中如何使用axios跨域访问数据(转)

    最近在项目中需要用到axios,所以就恶补一下这个axios到底是什么东东.越来它是vue-resource的替代品,官网也说了,以后都用axios, vue-resource不在维护.那么这个axi ...

  6. 设置 webstorm 对 .vue 高亮

    1. 首先安装vue插件,安装方法: setting  -->  plugin  ,点击plugin,在内容部分的左侧输入框输入vue,会出现两个关于vue的插件,点击安装即可.安装完成后,就可 ...

  7. (erase) Mispelling4 hdu1984

    Mispelling4 Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. shell函数与数组

    shell函数与数组 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.为什么要使用shell函数 简单的说函数的作用就是把程序里多次调用的相同的代码部分定义成一份,然后起个名字, ...

  9. PHP7 学习笔记(三)关于PHP7如何安装调试工具Xdebug扩展以及Zephir的问题

    前言: 1.自己摸索安装 2.快速安装 安装这个扩展是由于Zephir 编译不能始终通过,迫不得已啊,使用Zephir写扩展,总是出现以下错误: www@ubuntu1:~/phalcon-zephi ...

  10. java中生成验证码,以及验证码的使用

    java中生成验证码,以及验证码的使用: 1:验证码生成工具类: import java.awt.Color; import java.awt.Font; import java.awt.Graphi ...