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

题面

洛谷

题解

首先乘法取\(log\)变加法,开\(c\)次根变成除\(c\)。

于是问题等价于最大化\(\displaystyle \frac{\sum val_i}{c}\)。典型的分数规划的形式。

二分权值\(k\),每个点的点权变成\(val_i-k\),转为求最值,那么直接在\(AC\)自动机上\(dp\)就行了。

注意精度问题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define MAX 1505
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Node{int son[10],ff,s;double w;}t[MAX];
int tot;
void Insert(char *s,int val)
{
int l=strlen(s+1),u=0;
for(int i=1;i<=l;++i)
{
int c=s[i]-48;
if(!t[u].son[c])t[u].son[c]=++tot;
u=t[u].son[c];
}
t[u].w=log(val);t[u].s+=1;
}
int Q[MAX],L,R;
void BuildFail()
{
L=1;
for(int i=0;i<10;++i)if(t[0].son[i])Q[++R]=t[0].son[i];
while(L<=R)
{
int u=Q[L++];t[u].w+=t[t[u].ff].w;t[u].s+=t[t[u].ff].s;
for(int i=0;i<10;++i)
if(t[u].son[i])t[t[u].son[i]].ff=t[t[u].ff].son[i],Q[++R]=t[u].son[i];
else t[u].son[i]=t[t[u].ff].son[i];
}
}
char T[MAX],S[MAX];int n,m;
double f[MAX][MAX];int g1[MAX][MAX],g2[MAX][MAX];
void Tr(int i,int j,int k)
{
int v=t[j].son[k];
if(f[i][v]<f[i-1][j]+t[v].w)
{
f[i][v]=f[i-1][j]+t[v].w;
g1[i][v]=j;g2[i][v]=k;
}
}
bool check(double K)
{
for(int i=0;i<=tot;++i)t[i].w-=K*t[i].s;
int len=strlen(T+1);
for(int i=0;i<=len;++i)
for(int j=0;j<=tot;++j)f[i][j]=-1e300;
f[0][0]=0;
for(int i=1;i<=len;++i)
for(int j=0;j<=tot;++j)
if(T[i]=='.')for(int k=0;k<10;++k)Tr(i,j,k);
else Tr(i,j,T[i]-48);
double ans=-1e300;
for(int i=1;i<=tot;++i)ans=max(ans,f[len][i]);
for(int i=0;i<=tot;++i)t[i].w+=K*t[i].s;
return ans>0;
}
int main()
{
n=read();m=read();
scanf("%s",T+1);
for(int i=1,v;i<=m;++i)scanf("%s",S+1),v=read(),Insert(S,v);
BuildFail();
double l=0,r=21;
while(r-l>1e-3)
{
double mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
check(l);int pos=0,len=strlen(T+1);
for(int i=1;i<=tot;++i)if(f[len][i]>f[len][pos])pos=i;
for(int i=len;i;--i)S[i]=g2[i][pos]+48,pos=g1[i][pos];
for(int i=1;i<=len;++i)putchar(S[i]);puts("");
return 0;
}

[BJOI2019]奥术神杖(分数规划,动态规划,AC自动机)的更多相关文章

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

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

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

    对最终答案取对数,得到$\ln(Ans)=\frac{1}{c}\sum \ln(v_i)$,典型的分数规划问题.二分答案后,对所有咒语串建立AC自动机,然后套路地$f[i][j]$表示走到T的第i个 ...

  3. [BJOI2019]奥术神杖——AC自动机+DP+分数规划+二分答案

    题目链接: [BJOI2019]奥术神杖 答案是$ans=\sqrt[c]{\prod_{i=1}^{c}v_{i}}=(\prod_{i=1}^{c}v_{i})^{\frac{1}{c}}$. 这 ...

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

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

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

    题目大意: 给出一个长度 $n$ 的字符串 $T$,只由数字和点组成.你可以把每个点替换成一个任意的数字.再给出 $m$ 个数字串 $S_i$,第 $i$ 个权值为 $t_i$. 对于一个替换方案,这 ...

  6. [BJOI2019] 奥术神杖 [取log+AC自动机+dp]

    题面 传送门 思路 首先,看到这个乘起来开根号的形式,应该能想到用取$\log$的方式做一个转化: $\sqrt[n]{\prod_i a_i}=\frac{1}{n}\sum_i \log_b a_ ...

  7. luogu P5319 [BJOI2019]奥术神杖

    传送门 要求的东西带个根号,这玩意叫几何平均数,说到平均数,我们就能想到算术平均数(就是一般意义下的平均数),而这个东西是一堆数之积开根号,所以如果每个数取对数,那么乘法会变成加法,开根号变成除法,所 ...

  8. #loj3089 [BJOI2019]奥术神杖

    卡精度好题 最关键的一步是几何平均数的\(ln\)等于所有数字取\(ln\)后的算术平均值 那么现在就变成了一个很裸的01分数规划问题,一个通用的思路就是二分答案 现在来考虑二分答案的底层怎么写 把所 ...

  9. 【题解】Luogu P5319 [BJOI2019]奥术神杖

    原题传送门 题目让我们最大化\(val=\sqrt[k]{\prod_{i=1}^k w_i}\),其中\(k\)是咒语的个数,\(w_i\)是第\(i\)个咒语的神力 看着根号和累乘不爽,我们两边同 ...

随机推荐

  1. SpringBoot 2.0 mybatis mapper通用类

    <!---mybatis通用类包含mybatis和连接池 mybatis和连接池就不需要引入--> <dependency> <groupId>tk.mybatis ...

  2. Yii2设计模式——简单工厂模式

    除了使用 new 操作符之外,还有更多的制造对象的方法.你将了解到实例化这个活动不应该总是公开进行,也会认识到初始化经常造成"耦合"问题. 应用举例 yii\db\mysql\Sc ...

  3. 硬杠后端(后端坑系列)——Django前期工作

    Django是一个开放源代码的Web应用框架,由Python写成,采用了MVC的框架模式. MVC MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个部件 ...

  4. 洛谷P2664 树上游戏(点分治)

    题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...

  5. Hacking Bsides Vancouver 2018 walkthrough

    概述: Name: BSides Vancouver: 2018 (Workshop) Date release: 21 Mar 2018 Author: abatchy Series: BSides ...

  6. Android - 文字向上翻滚效果的实现

    本文转载https://xwc2013.iteye.com/blog/1976051 今天看到了一种文字翻滚的效果,感觉非常实用.所以就自己试着做出了这种效果,现在把它分享给大家! 首先在res目录下 ...

  7. Android Intent通讯实例

    //1.拨打电话 // 给移动客服10086拨打电话 Uri uri = Uri.parse("tel:10086"); Intent intent = new Intent(In ...

  8. 查看SQL Server服务运行帐户和SQL Server的所有注册表项

    查看SQL Server服务运行帐户和SQL Server的所有注册表项 SELECT * FROM sys.dm_server_registry SELECT * FROM sys.dm_serve ...

  9. 简单shellcode编写

    0x00 介绍 Shellcode 是指经过精心设计的一串指令,一旦注入正在运行的应用程序中即可运行,常用于栈和基于堆的溢出.术语Shellcode意思指的便是用于启动一个命令Shell的已编写好的可 ...

  10. 自反ACL(第三组)

    一.实验拓扑 二.配置过程 此处我用了学号后两位来划分网段,注意:先把网络做通再配ACL 1)网络连通测试 内网可以telnet外网 ----------- 外网可以telnet内网 2)ACL配置( ...