题目链接:

[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. 利用贝叶斯算法实现手写体识别(Python)

    在开始介绍之前,先了解贝叶斯理论知识 https://www.cnblogs.com/zhoulujun/p/8893393.html 简单来说就是:贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯 ...

  2. zTree插件实现菜单树

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta ht ...

  3. js入门之函数

    一. 函数 函数可以封装一段特定功能的代码,然后通过函数名可以重复调用 1 .函数的定义 funcation 函数名 (){ 函数体 } 函数名() 调用函数 2. 函数的参数 funcation f ...

  4. iOS8中UIActionSheet弹出UIImagePickerController异常处理

    iOS8之后,UIActionSheet改父于UIAlertController.带来了一丢丢兼容性的问题. 比如在弹出的actionsheet中选择从相册选择图片或者拍照,之后弹出UIImagePi ...

  5. Dephi 10.3.3试用报告

    官方没有正式发布,但出了下载及keygen,具体内容我在这篇内容写了:Delphi 10.3.3最新消息 . 也可以去Delphi多层开发交流QQ群:209321818找相关的keygen. 今早来就 ...

  6. jar下载及Maven配置整理

    Spring的各版本jar包下载地址http://repo.spring.io/release/org/springframework/spring/ springframework下载地址https ...

  7. mac使用sourcetree跳过注册

    转自https://blog.csdn.net/qq_32890891/article/details/89216954 打开sourcetree 关闭sourcetree 命令终端输入default ...

  8. assert函数应用

    目录 1 assert概念 2 assert作用 3 assert用法 3.1 检测调用者传过来的指针参数是否正常 3.2 判断某个变量的范围 3.3 assert只检验一个地方 3.4 不能使用改变 ...

  9. linux(3)

    一.用户和组的管理 Linux/Unix是多用户系统: root是超级用户,拥有最高权限.其它用户及权限由root来管理.对比Windows系统: 控制面板 -> 管理工具 -> 计算机管 ...

  10. 14、RALM: 实时 look-alike 算法在推荐系统中的应用

    转载:https://zhuanlan.zhihu.com/p/71951411 RALM: 实时 look-alike 算法在推荐系统中的应用 0. 导语 本论文题为<Real-time At ...