题目链接:

[BJOI2019]奥术神杖

答案是$ans=\sqrt[c]{\prod_{i=1}^{c}v_{i}}=(\prod_{i=1}^{c}v_{i})^{\frac{1}{c}}$。

这样不大好求,我们将这个式子取$ln$,变成$ln\ ans=\frac{1}{c}\sum_{i=1}^{c}ln\ v_{i}$。

这显然是一个分数规划,每次二分一个答案$mid$,将每个串的权值都减去$mid$,那么只需要求最大价值是否大于$0$即可。

剩下的问题就是一个在$AC$自动机上的$DP$了,设$f[i][j]$表示在$AC$自动机上的点$j$,已经匹配的长度为$i$时的最大值,在$AC$自动机上转移即可。

在$DP$时还要记录一下每个状态从哪个点转移过来以便输出方案。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-5;
int end[2000];
double f[2000][2000];
int g[2000][2000];
int fail[2000];
int tr[2000][10];
int cnt;
double val[2000];
char ch[2000];
char s[2000];
int now;
int n,m;
int v;
double ans;
void build(char *ch,int v)
{
int len=strlen(ch);
now=0;
for(int i=0;i<len;i++)
{
int x=ch[i]-'0';
if(!tr[now][x])
{
tr[now][x]=++cnt;
}
now=tr[now][x];
}
end[now]++;
val[now]+=log(v);
}
void get_fail()
{
queue<int>q;
for(int i=0;i<=9;i++)
{
if(tr[0][i])
{
q.push(tr[0][i]);
}
}
while(!q.empty())
{
now=q.front();
q.pop();
val[now]+=val[fail[now]];
end[now]+=end[fail[now]];
for(int i=0;i<=9;i++)
{
if(tr[now][i])
{
fail[tr[now][i]]=tr[fail[now]][i];
q.push(tr[now][i]);
}
else
{
tr[now][i]=tr[fail[now]][i];
}
}
}
}
double DP(double mid)
{
for(int i=0;i<=n;i++)
{
for(int j=0;j<=cnt;j++)
{
f[i][j]=-1e9;
g[i][j]=0;
}
}
f[0][0]=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<=cnt;j++)
{
if(f[i][j]>-1e9)
{
if(s[i+1]=='.')
{
for(int k=0;k<=9;k++)
{
if(f[i+1][tr[j][k]]<f[i][j]+val[tr[j][k]]-mid*end[tr[j][k]])
{
f[i+1][tr[j][k]]=f[i][j]+val[tr[j][k]]-mid*end[tr[j][k]];
g[i+1][tr[j][k]]=j;
}
}
}
else
{
int x=s[i+1]-'0';
if(f[i+1][tr[j][x]]<f[i][j]+val[tr[j][x]]-mid*end[tr[j][x]])
{
f[i+1][tr[j][x]]=f[i][j]+val[tr[j][x]]-mid*end[tr[j][x]];
g[i+1][tr[j][x]]=j;
}
}
}
}
}
double res=-1e9;
for(int i=0;i<=cnt;i++)
{
res=max(res,f[n][i]);
}
return res;
}
void print(int dep,int now)
{
if(!dep)
{
return ;
}
print(dep-1,g[dep][now]);
if(s[dep]!='.')
{
printf("%c",s[dep]);
return ;
}
else
{
for(int i=0;i<=9;i++)
{
if(tr[g[dep][now]][i]==now)
{
printf("%c",i+'0');
return ;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for(int i=1;i<=m;i++)
{
scanf("%s%d",ch,&v);
build(ch,v);
}
get_fail();
double l=0,r=22;
while(r-l>eps)
{
double mid=(l+r)/2;
if(DP(mid)>0)
{
l=mid;
ans=mid;
}
else
{
r=mid;
}
}
DP(ans);
for(int i=0;i<=cnt;i++)
{
if(f[n][i]>0)
{
print(n,i);
break;
}
}
}

[BJOI2019]奥术神杖——AC自动机+DP+分数规划+二分答案的更多相关文章

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

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

  2. P5319-[BJOI2019]奥术神杖【0/1分数规划,AC自动机,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5319 题目大意 一个长度为\(n\)的串\(T\),用\(0\sim 9\)填充所有的\(.\). 然后给出\( ...

  3. 【Luogu】P3705新生舞会(费用流+分数规划+二分答案)

    题目链接 本来以为自己可以做出来,结果……打脸了 (貌似来wc立了好几个flag了,都没竖起来) 不过乱蒙能蒙出一个叫“分数规划”的东西的式子还是很开心的 观察$C=\frac{a_{1}+a_{2} ...

  4. [SDOI2017] 新生舞会 - 二分图最大权匹配,分数规划,二分答案

    有一个二分图,每个部都有 \(n\) 个点,每条边有两个参数 \(a_e, b_e\),求一种匹配,使得 \(\sum a_i / \sum b_i\) 最大 Solution 显然的分数规划,考虑二 ...

  5. poj2728 生成树01分数规划 (二分答案)

    给定整数序列a,b,求出下式的最大值 sum{ai*xi}/sum{bi*xi},xi=0|1 通俗来说,就是选出一些整数对(ai,bi),使得选出的a之和与选出的b之和商最大化 二分答案L,即选出的 ...

  6. hdu6070(分数规划/二分+线段树区间更新,区间最值)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意: 给出一个题目提交序列, 从中选出一个正确率最小的子串. 选中的子串中每个题目当且仅当最 ...

  7. luoguP5319 [BJOI2019]奥术神杖(分数规划,AC自动机DP)

    luoguP5319 [BJOI2019]奥术神杖(分数规划,AC自动机DP) Luogu 题解时间 难点在于式子转化,设有c个满足的子串,即求最大的 $ ans = \sqrt[c]{\prod_{ ...

  8. [BJOI2019]奥术神杖(分数规划,动态规划,AC自动机)

    [BJOI2019]奥术神杖(分数规划,动态规划,AC自动机) 题面 洛谷 题解 首先乘法取\(log\)变加法,开\(c\)次根变成除\(c\). 于是问题等价于最大化\(\displaystyle ...

  9. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

随机推荐

  1. C# explicit interface implementation(显式接口实现)

    C# explicit interface implementation 某个类要实现两个包含相同方法名的接口, 应该如何实现这两个方法? namespace ExplicitInterfaceImp ...

  2. DataGridView绑定数据、删除数据

    定义学生类: using System; using System.Collections.Generic; using System.Linq; using System.Text; using S ...

  3. mac OS下 安装MySQL 5.7

    Mac OS X 下 TAR.GZ 方式安装 MySQL 5.7 与 MySQL 5.6 相比, 5.7 版本在安装时有两处不同: 1:初始化方式改变, 从scripts/mysql_install_ ...

  4. class类 - extends

    继承是面向对象中一个比较核心的概念.ES6 class的继承与java的继承大同小异,如果学过java的小伙伴应该很容易理解,都是通过extends关键字继承.相较于ES5当中通过原型链继承要清晰和方 ...

  5. js如何获取数值

    获取jsfunction返回的值1,首先,用初始化代码创建一个新的HTML5文件,如下所示.2,创建一个新的H1标记来接收JS中函数休闲鹿的返回值.3,创建一个新的脚本标记并在标记中创建一个新函数.函 ...

  6. Java 之 JDK9 对集合添加的优化

    通常,在代码中创建一个集合(例如,List 或 Set ),并直接用一些元素填充它. 实例化集合,几个 add方法调用,使得代码重复. Java 9,添加了几种集合工厂方法,更方便创建少量元素的集合. ...

  7. Flutter自定义绘制(1)- 绘制基础

    CustomPainter Flutter 中实现绘制的主要是CustomPainter类. 我们一般继承这个类,来使用它: class MyPainter extends CustomPainter ...

  8. Ubuntu 远程管理常用命令

    目标 关机/重启 shutdown 查看或配置网卡信息 ifconfig ping 远程登录和复制文件 ssh scp 01. 关机/重启 序号 命令 对应英文 作用 01 shutdown 选项 时 ...

  9. Image Processing and Analysis_21_Scale Space:Scale-Space for Discrete Signals——1990

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  10. C# 开发的windows服务 不能调试——讨论整理

    CSDN的标题:C# 开发的windows服务 不能调试 System.Diagnostics.Debugger.Launch();在想加断点的地方加入这行,是进入断点的,可以进行调试,我的是xp系统 ...