luogu P5319 [BJOI2019]奥术神杖
要求的东西带个根号,这玩意叫几何平均数,说到平均数,我们就能想到算术平均数(就是一般意义下的平均数),而这个东西是一堆数之积开根号,所以如果每个数取对数,那么乘法会变成加法,开根号变成除法,所以我们只要最大化\(\frac{\sum_i ln_{a_i}}{c}\)就行了
这是一个分数规划的形式,首先二分最终答案\(mid\),然后我们要求最大答案,所以要检查\(\frac{\sum_i ln_{a_i}}{c}\)是否可以\(\ge mid\),可以改成$$\sum_i ln_{a_i}\ge mid*c$$$$\sum_i ln_{a_i}-mid\ge 0$$
所以出现一个串,权值加上\(ln_{a_i}-mid\),并且这是多个串在一个串上匹配,所以可以建出AC自动机后dp,设\(f_{i,j}\),表示放完前\(i\)个字符,在自动机的\(j\)处的最大权值,转移枚举下一位放什么转移(如果下一位确定就只能用那个字符),每到一个点就加上这个点权值,这个点权值为这个点以及跳\(fail\)能到的点的\(\sum ln_{a_i}-mid\).转移时顺便记录从哪转移,就可以倒序输出方案了
实现优秀的话\(eps\)可以开到\(1e-3\)
// luogu-judger-enable-o2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<map>
#include<set>
#define LL long long
#define db double
using namespace std;
const int N=1500+10;
const db eps=1e-3;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
char cc[N],ss[N],an[N];
db ma,a[N],nm[N],f[N][N];
int n,m,ch[N][10],fl[N],tt,pr[N][N][2];
void inst()
{
scanf("%s",ss+1);
int len=strlen(ss+1),x=0;
db va=log(rd());
ma=max(ma,va);
for(int i=1;i<=len;++i)
{
if(!ch[x][ss[i]-'0']) ch[x][ss[i]-'0']=++tt;
x=ch[x][ss[i]-'0'];
}
a[x]+=va,++nm[x];
}
void bui()
{
queue<int> q;
for(int i=0;i<10;++i)
if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty())
{
int x=q.front();
q.pop();
a[x]+=a[fl[x]],nm[x]+=nm[fl[x]];
for(int i=0;i<10;++i)
{
if(ch[x][i]) fl[ch[x][i]]=ch[fl[x]][i],q.push(ch[x][i]);
else ch[x][i]=ch[fl[x]][i];
}
}
}
void print(int x,int j)
{
if(!x) return;
an[x]=pr[x][j][1]+'0',print(x-1,pr[x][j][0]);
}
int main()
{
n=rd(),m=rd();
scanf("%s",cc+1);
while(m--) inst();
bui();
for(int i=1;i<=tt;++i) f[0][i]=-1e9;
db l=0,r=ma;
while(r-l>eps)
{
db mid=(l+r)/2;
for(int i=1;i<=n;++i)
{
for(int j=0;j<=tt;++j) f[i][j]=-1e9;
for(int j=0;j<=tt;++j)
{
if(fabs(f[i-1][j]-1e9)<1) continue;
int st=0,en=9;
if(cc[i]>='0'&&cc[i]<='9') st=en=cc[i]-'0';
for(int k=st;k<=en;++k)
{
int nt=ch[j][k];
if(f[i][nt]<f[i-1][j]+a[nt]-nm[nt]*mid)
f[i][nt]=f[i-1][j]+a[nt]-nm[nt]*mid,pr[i][nt][0]=j,pr[i][nt][1]=k;
}
}
}
int jj=0;
db mx=f[n][0];
for(int j=1;j<=tt;++j)
if(mx<f[n][j]) mx=f[n][j],jj=j;
if(mx>eps)
{
print(n,jj);
l=mid+eps;
}
else r=mid-eps;
}
for(int i=1;i<=n;++i) putchar(an[i]);
return 0;
}
luogu P5319 [BJOI2019]奥术神杖的更多相关文章
- 【题解】Luogu P5319 [BJOI2019]奥术神杖
原题传送门 题目让我们最大化\(val=\sqrt[k]{\prod_{i=1}^k w_i}\),其中\(k\)是咒语的个数,\(w_i\)是第\(i\)个咒语的神力 看着根号和累乘不爽,我们两边同 ...
- luoguP5319 [BJOI2019]奥术神杖(分数规划,AC自动机DP)
luoguP5319 [BJOI2019]奥术神杖(分数规划,AC自动机DP) Luogu 题解时间 难点在于式子转化,设有c个满足的子串,即求最大的 $ ans = \sqrt[c]{\prod_{ ...
- [BJOI2019]奥术神杖(分数规划,动态规划,AC自动机)
[BJOI2019]奥术神杖(分数规划,动态规划,AC自动机) 题面 洛谷 题解 首先乘法取\(log\)变加法,开\(c\)次根变成除\(c\). 于是问题等价于最大化\(\displaystyle ...
- [BJOI2019]奥术神杖——AC自动机+DP+分数规划+二分答案
题目链接: [BJOI2019]奥术神杖 答案是$ans=\sqrt[c]{\prod_{i=1}^{c}v_{i}}=(\prod_{i=1}^{c}v_{i})^{\frac{1}{c}}$. 这 ...
- [BJOI2019]奥术神杖
https://www.luogu.org/problemnew/show/P5319 题解 首先观察我们要求的答案的形式: \[ \biggl(\prod V_i \biggr)^x\ \ \ x= ...
- [BJOI2019]奥术神杖(分数规划+AC自动机+DP)
题解:很显然可以对权值取对数,然后把几何平均值转为算术平均值,然后很显然是分数规划.先对每个模式串建立AC自动机,每个节点w[i],sz[i]分别表示以其为前缀的字符串,然后再二分最优解k,然后w[i ...
- #loj3089 [BJOI2019]奥术神杖
卡精度好题 最关键的一步是几何平均数的\(ln\)等于所有数字取\(ln\)后的算术平均值 那么现在就变成了一个很裸的01分数规划问题,一个通用的思路就是二分答案 现在来考虑二分答案的底层怎么写 把所 ...
- [BJOI2019]奥术神杖(AC自动机,DP,分数规划)
题目大意: 给出一个长度 $n$ 的字符串 $T$,只由数字和点组成.你可以把每个点替换成一个任意的数字.再给出 $m$ 个数字串 $S_i$,第 $i$ 个权值为 $t_i$. 对于一个替换方案,这 ...
- [BJOI2019] 奥术神杖 [取log+AC自动机+dp]
题面 传送门 思路 首先,看到这个乘起来开根号的形式,应该能想到用取$\log$的方式做一个转化: $\sqrt[n]{\prod_i a_i}=\frac{1}{n}\sum_i \log_b a_ ...
随机推荐
- 任意N个不同数的逆序对平均值
在学习数据结构的时候看到了以下定理: 但是老师并没有解释,本着钻研的精神决定搞清楚为什么是这个数. 在百度 google一番之后并没有找到,决定自己试着证明. 最开始走了一些弯路,但突然灵光一闪很容易 ...
- JVM内存结构简单认知
关于JVM的面试传送门:https://blog.csdn.net/shengmingqijiquan/article/details/77508471 JVM内存结构主要划分为:堆,jvm栈,本地方 ...
- pytorch的函数中的dilation参数的作用
如果我们设置的dilation=0的话,效果如图: 蓝色为输入,绿色为输出,可见卷积核为3*3的卷积核 如果我们设置的是dilation=1,那么效果如图: 蓝色为输入,绿色为输出,卷积核仍为3*3, ...
- HTML基础知识个人总结
[学习的网站是主要是W3school,还加上一些其他搜索学习到的内容,仅在博客做个人整理] 一.标签——尖括号围成的关键词,成对出现. ※使用时必须符合标签嵌套规则 1. (1) <!DOCTY ...
- 团队开发项目--NABCD模型
N(need)需求: 鉴于在学校中的大部分爱学习的学生平时都去拍空教室的占有情况,我们发现有的时候太多,导致同学们们拍照会浪费很长的时间,而且空教室的显示不是一下子全出来,有的时候还会出现无法显示的情 ...
- Python_自定义递归的最大深度
自定义递归的最大深度 python默认的最大递归深度为998,在有些情况下是不够用,需要我们自行设置.设置方式如下: import sys sys.setrecursionlimit(num) # n ...
- 回忆曾经的SSM框架实现文件上传
近期在使用springboot实现文件上传的功能,想到曾经用SSM做过这个功能,在这里记录一下过去实现的方式 maven添加文件上传所需的依赖 springMVC的配置文件配置一下文件上传 我实现的是 ...
- Win10开机“提示语音”以及”随机播放音乐”
1.在桌面建立一个.txt文件 2.把一下代码拷贝进去: RandomizeCreateObject("SAPI.SpVoice").Speak"先生,为你播放一首mus ...
- 使用lambda表达式对相同属性的实体进行合并
List<CrmAuthorizedInfo> crmAuthorizedInfos = flowPlanInfoMapper.findAllByEncode(stationForm.ge ...
- api跨域
1.找方法名称是get开头的2.找get请求类型的 自定义webapi的路由规则,控制到action 1.跨域设置:(服务端)webconfig文件中,system.webServer节点下添加 &l ...