题目链接:

[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. 内置函数----format

    说明: 1. 函数功能将一个数值进行格式化显示. 2. 如果参数format_spec未提供,则和调用str(value)效果相同,转换成字符串格式化. >>> format(3.1 ...

  2. YAPI安装和使用

    .本人已验证,参考文档:https://blog.csdn.net/qq_39429962/article/details/84000460 很详细.

  3. CentOS7使用yum安装PostgreSQL和PostGIS

    更新yum源 CentOS7默认yum源的PostgreSQL版本过低,不适合在本版本上使用.在https://yum.postgresql.org/repopackages.php上找到适合Cent ...

  4. ASE19团队项目 beta阶段 model组 scrum report list

    scrum 1 scrum 2 scrum 3 scrum 4 scrum 5 scrum 6 scrum 7

  5. [LeetCode] 784. 字母大小写全排列 ☆☆☆(回溯、深度优先遍历)

    https://leetcode-cn.com/problems/letter-case-permutation/solution/shen-du-you-xian-bian-li-hui-su-su ...

  6. Linq以本周和本月为条件的Sql,Liqn查询本周,Linq查询本月

    //计算本周时间 时间 > DateTime.Now.AddDays(-Convert.ToInt32(DateTime.Now.Date.DayOfWeek) //计算本月时间 时间 > ...

  7. 台式机电脑u盘启动识别不到U盘设置

    U盘作为一个引导盘,在装机过程中显得十分的方便,有时候我们可以将U盘做成一个PE启动盘,有时我们也可以直接将U盘做成一个操作系统光盘的镜像. 但是有时候我们辛辛苦苦将U盘做成了引导盘了,关机---&g ...

  8. Tomcat 项目结构完整解析

    本文主要为了对我们平时Tomcat中,我们经常会涉及到的项目结构做一个解析,以便可以一目了然的知道有哪些结构及其作用. 最近一直在思考,怎么样才能一目了然,初步考虑,即用浏览器打开页面,不用往下滑动, ...

  9. MySQL进阶8 分页查询(limit) - 【SQL查询语法执行顺序及大致结构】- 子查询的3个经典案例

    #进阶8 分页查询 /* 应用场景: 当要显示的数据,一页显示不全,需要分页提交sql请求 语法: select 查询列表 #7 from 表1 #执行顺序:#1 [join type join 表2 ...

  10. 《流畅的Python》 Sequence Hacking, Hashing and Slicing(没完成)

    序列修改,散列和切片 基本序列协议:Basic sequence protocol: __len__ and __getitem__ 本章通过代码讨论一个概念: 把protocol当成一个正式接口.协 ...