题目链接:

[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;}}
}

转载于:https://www.cnblogs.com/Khada-Jhin/p/10772191.html

[BJOI2019]奥术神杖——AC自动机+DP+分数规划+二分答案相关推荐

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

    正题 题目链接:https://www.luogu.com.cn/problem/P5319 题目大意 一个长度为nnn的串TTT,用0∼90\sim 90∼9填充所有的.... 然后给出mmm个串和 ...

  2. P1768-天路【负环,SPFA,01分数规划,二分答案】

    正题 题目链接:https://www.luogu.org/problemnew/show/P1768 题目大意 求一条回路使得路上∑vi∑pi\frac{\sum v_i}{\sum p_i}∑pi ...

  3. [jzoj 4230] 淬炼神体{ 0/1分数规划+二分答案}

    题目 Description 王仙女将你提供的答案填在<葵花宝典>上,突然,宝典发出耀眼的白光,一股强大的吸力瞬间将仙女吸入宝典中. 一阵眩晕过后,仙女发现自己来到了一个浮岛上,四周的半空 ...

  4. HDU 2296 Ring AC自动机 + DP

    题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串 ...

  5. uvalive4842(AC自动机+DP)

    题意: 给出猴子打字时打某个字母的概率,猴子最多可以敲键盘m次,问得到的长度是m的单词包含模式串的概率. 思路: AC自动机+dp. 首先,我们用模式串构造一个AC自动机,用dp[i]][j]表示当前 ...

  6. bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5187  Solved: 2136 [Submit][St ...

  7. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

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

    题解:很显然可以对权值取对数,然后把几何平均值转为算术平均值,然后很显然是分数规划.先对每个模式串建立AC自动机,每个节点w[i],sz[i]分别表示以其为前缀的字符串,然后再二分最优解k,然后w[i ...

  9. 牛客 - Connie(AC自动机+dp/KMP+dp)

    题目链接:点击查看 题目大意:给出一个匹配串 sss,现在问模式串 ttt 的期望得分.其中假设匹配串在模式串中的出现次数为 xxx,那么将得到 2x2^x2x 的分数 题目分析:涉及到了期望一开始还 ...

最新文章

  1. 使用神经网络生成抽象随机艺术
  2. 浅谈JDBC与ODBC的区别与应用
  3. 自动化测试工具的选择
  4. js调试微博登录案例
  5. 基于 Kyma 的企业级云原生应用的扩展案例分享
  6. numpy拼接_巧用numpy切分图片
  7. printf打印百分号%
  8. 攻克学习多线程时碰到的难题(zz)
  9. 003之MFCSocket异步编程(指针机制)
  10. 【OpenCV新手教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑
  11. python中execute函数_在excel中调用python函数
  12. 盲源分离(BSS)的学习总结(PCA、ICA)
  13. git 和gitHup工具笔记的详细教程
  14. JMeter Ramp-up 说明
  15. QQ聊天记录的相关代码
  16. python 微博_用python发微博
  17. C语言考试题库之填空题
  18. 树莓派开发ADC芯片CS1237(C语言和python库开发)
  19. loj534. 「LibreOJ Round #6」花团
  20. 如何用Python 求函数 y = sinx 在区间[0, pi/2]上的弧长

热门文章

  1. Android三方SDK国际化(汉化)
  2. Android应用开发之( TableLayout中stretchColumns、shrinkColumns的用法)
  3. 高并发计数器、红包、二维码使用如下
  4. 华为昇腾系列开发入门教程一:简单的几个名词
  5. 考研党特有的错觉,你中了几个?
  6. [论文阅读] 信息安全领域四大顶会
  7. 职场中,受益终生的五种思维
  8. 转载一篇比较详细的讲解html,css的一篇文章,很长
  9. vivado CLOCK_DEDICATED_ROUTE约束的使用
  10. (kuang)1、Spring 笔记