https://www.luogu.org/problemnew/show/P5319

题解

首先观察我们要求的答案的形式:

\[\biggl(\prod V_i \biggr)^x\ \ \ x=\frac{1}{c}
\]

这个东西貌似还不能最优化,根据套路论,把这个东西整体取个\(ln\),于是就变成了:

\[ln\biggl(\biggl(\prod V_i \biggr)^x\biggr)=\frac{1}{x}\sum ln(V_i)
\]

然后这个东西就可以分数规划了,验证的话跑个dp就好了。

有一点就是必须匹配至少一个串,题解好像在状态里加了一维0/1表示有没有匹配到一个串,我是偷懒直接加了个\(eps\)。

代码

#include<bits/stdc++.h>
#define N 1509
using namespace std;
typedef long long ll;
const double eps=1e-5;
queue<int>q;
double dp[N][N],cnt[N],mx[N],w;
int tot,ch[N][10],f[N],n,m,tag1[N][N],tag2[N][N];
char s[N],s1[N];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
inline void ins(int len){
int now=0;
for(int i=1;i<=len;++i){
if(!ch[now][s1[i]-'0'])ch[now][s1[i]-'0']=++tot;
now=ch[now][s1[i]-'0'];
}
mx[now]+=w;cnt[now]++;
}
inline void build(){
for(int i=0;i<10;++i)if(ch[0][i])q.push(ch[0][i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<10;++i){
if(ch[u][i])f[ch[u][i]]=ch[f[u]][i],mx[ch[u][i]]+=mx[ch[f[u]][i]],
cnt[ch[u][i]]+=cnt[ch[f[u]][i]],q.push(ch[u][i]);
else ch[u][i]=ch[f[u]][i];
}
}
}
inline bool check(double mid){
memset(dp,-0x3f,sizeof(dp));
dp[0][0]=0;
// printf("%.2lf ",mid);
for(int i=1;i<=n;++i){
// printf(" ");
for(int j=0;j<=tot;++j){
if(s[i]=='.')
for(int k=0;k<10;++k){
int x=ch[j][k];
double xx=dp[i-1][j]+mx[x]-mid*cnt[x];
// printf("%.2lf ",xx);
if(xx>dp[i][x]){
dp[i][x]=xx;
tag1[i][x]=k;tag2[i][x]=j;
}
}
else{
int x=ch[j][s[i]-'0'];
double xx=dp[i-1][j]+mx[x]-mid*cnt[x];
if(xx>dp[i][x]){
dp[i][x]=xx;
tag2[i][x]=j;
}
}
}
}
// puts("");
for(int j=0;j<=tot;++j)if(dp[n][j]>eps)return 1;
return 0;
}
void dfs(int len,int now){
if(!len)return;
if(s[len]=='.')s[len]=tag1[len][now]+'0';
dfs(len-1,tag2[len][now]);
// cout<<now<<" ";printf("%.2lf ",dp[len][now]);
}
int main(){
n=rd();m=rd();
double l=0,r=0;
scanf("%s",s+1);
for(int i=1;i<=m;++i){
scanf("%s",s1+1);w=log((double)rd());
r=max(r,w);
ins(strlen(s1+1));
}
r+=1000;
build();
while(l+eps<r){
double mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
// printf("%.2lf\n",l);
check(l);
for(int j=0;j<=tot;++j)if(dp[n][j]>eps){
dfs(n,j);break;
}
printf("%s",s+1);
return 0;
}

[BJOI2019]奥术神杖的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. luogu P5319 [BJOI2019]奥术神杖

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

  7. #loj3089 [BJOI2019]奥术神杖

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

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

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

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

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

随机推荐

  1. 基础知识:语言、编程、计算机组成、cpu、存储器

    2019年3月18日一.    语言:一种事物与另外一种事物沟通的介质.              编程语言:程序员与计算机沟通的介质.    编程:把要让计算机做的事用一种编程语言表达出来.    ...

  2. Redis 过期键删除策略

    Redis 中数据库键的过期时间都保存在过期字典中,当一个键过期了,Redis 存在三种不同的删除策略:定时删除.惰性删除和定期删除 定时删除 定义 在设置键的过期时间的同时创建一个计时器,让定时器在 ...

  3. webpack 单独打包指定JS文件(CopyWebpackPlugin)

    背景: 不确定打出的前端包所访问的后端IP,需要对项目中IP配置文件单独拿出来,方便运维部署的时候对IP做修改.因此,需要用webpack单独打包指定文件.npm install --save-dev ...

  4. Spring boot入门(三):SpringBoot集成结合AdminLTE(Freemarker),利用generate自动生成代码,利用DataTable和PageHelper进行分页显示

    关于SpringBoot和PageHelper,前篇博客已经介绍过Spring boot入门(二):Spring boot集成MySql,Mybatis和PageHelper插件,前篇博客大致讲述了S ...

  5. Dynamics 365中的批量删除作业执行频率可以高于每天一次吗?

    微软动态CRM专家罗勇 ,回复317或者20190314可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 我先来做一个例子,登 ...

  6. openlayers 3方法继承

    之前Web GIS开发使用的ArcGIS API用起来很系统,但是使用开源Web GIS API已经成主流趋势(你懂的~),最近项目想要从ArcGIS API 转到openlayers API,用起来 ...

  7. VS fopen sprinft ... unsafe 问题

    我的用的是VS2017 VS项目->右键属性(最下面)->C/C++->预处理器->预处理器定义->编辑->加上_CRT_SECURE_NO_WARNINGS  - ...

  8. 章节十、3-CSS Selector---用CSS Selector - ID定位元素

    一.如果元素的 ID 不唯一,或者是动态的,或者 name 以及 linktext 属性值也不唯一,对于这样的元素,我们 就需要考虑用 xpath或者css selector 来查找元素了,然后再对元 ...

  9. MyDAL - 引用类型对象 .DeepClone() 深度克隆[深度复制] 工具 使用

    索引: 目录索引 一.API 列表 .DeepClone() 用于 Model / Entity / ... ... 等引用类型对象的深度克隆 特性说明 1.不需要对对象做任何特殊处理,直接 .Dee ...

  10. MySQL下载与MySQL安装图解(MySQL5.7与MySQL8.0)

    MySQL下载与MySQL安装图解(MySQL5.7与MySQL8.0) 1.MySQL下载(MySQL8.0社区版) mysql下载方法,请根据风哥以下步骤与图示来下载mysql8.0最新社区版本: ...