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

Luogu

题解时间

难点在于式子转化,设有c个满足的子串,即求最大的 $ ans = \sqrt[c]{\prod_{ i = 1 }^{ c } w_{i} } $ 。

取个对数变成 $ \ln Ans = \frac{1}{c} \sum_{ i = 1 } ^ { c } \ln w_{i} $ 。

很明显是0/1分数规划。

二分mid倒腾一下式子变成 $ \sum_{ i = 1 }^{ c } ( \ln w_{i} - mid ) > 0 $ 。

然后就随便做了。

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}};
template<typename TP>inline void read(TP &tar)
{
TP ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
tar=ret*f;
}
namespace RKK
{
const int N=1511;
const double eps=1e-6; int n,m;double w[N];
char str[N],rts[N]; int tcnt=0,to[N][10],fail[N],cnt[N];double v[N];
void insert(char *s,int id)
{
int len=strlen(s+1),px=0;
for(int i=1;i<=len;i++)
{
int &t=to[px][s[i]-'0'];
if(!t) t=++tcnt;px=t;
}
cnt[px]++,v[px]+=w[id];
}
queue<int> q;
void getfail()
{
for(int i=0;i<10;i++)if(to[0][i]) q.push(to[0][i]);
while(!q.empty())
{
int px=q.front();q.pop();
for(int i=0;i<10;i++)
{
int &t=to[px][i];
if(!t) t=to[fail[px]][i];
else fail[t]=to[fail[px]][i],cnt[t]+=cnt[fail[t]],v[t]+=v[fail[t]],q.push(t);
}
}
}
double dp[N][N];
int fr[N][N],g[N][N];
int work(double k)
{
for(int i=0;i<=n;i++)for(int j=0;j<=tcnt;j++) dp[i][j]=-1e18;
dp[0][0]=0;for(int i=1;i<=n;i++)for(int j=0;j<=tcnt;j++)if(dp[i-1][j]!=-1e18)
for(int b=0;b<10;b++)if(str[i]=='.'||str[i]-'0'==b)
{
int px=to[j][b];if(dp[i][px]<dp[i-1][j]+v[px]-k*cnt[px])
dp[i][px]=dp[i-1][j]+v[px]-k*cnt[px],fr[i][px]=j,g[i][px]=b;
}
double ret=-1e18;for(int i=0;i<=tcnt;i++) ret=max(ret,dp[n][i]);return ret>0;
} int prt[N];
int main()
{
scanf("%d%d%s",&n,&m,str+1);
for(int i=1;i<=m;i++)
scanf("%s%lf",rts+1,&w[i]),w[i]=log(w[i]),insert(rts,i);
getfail();
double ql=0,qr=21,qm,qa=0;
while(qr-ql>eps)
qm=(ql+qr)/2,work(qm)?qa=qm,ql=qm:qr=qm;
work(qa);
int px=0;for(int i=0;i<=tcnt;i++)if(dp[n][i]>0){px=i;break;}
for(int i=n;i;i--) prt[i]=g[i][px],px=fr[i][px];
for(int i=1;i<=n;i++) printf("%d",prt[i]);putchar('\n');
return 0;
}
}
int main(){return RKK::main();}

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

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

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

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

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

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

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

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

    正题 题目链接:https://www.luogu.com.cn/problem/P5319 题目大意 一个长度为\(n\)的串\(T\),用\(0\sim 9\)填充所有的\(.\). 然后给出\( ...

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

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

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

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

  7. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

  8. HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...

  9. HDU2457 DNA repair(AC自动机+DP)

    题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...

随机推荐

  1. Solution -「NOI 2021」「洛谷 P7740」机器人游戏

    \(\mathcal{Description}\)   Link.   自己去读题面叭~ \(\mathcal{Solution}\)   首先,参悟[样例解释 #2].一种暴力的思路即为钦定集合 \ ...

  2. IDEA 2021 没有Allow parallel run

    IDEA 2021 没有Allow parallel run 尝试运行多个客户端. 新版IDEA找不到Allow parallel run

  3. 超详细的Cookie增删改查

    目录 1,什么是 Cookie? 1.1,存储形式 1.2,常用属性 1.3,大小限制 2,增 or 改Cookie 3,查Cookie 4,删Cookie 1,什么是 Cookie? Cookie是 ...

  4. Nginx安装启用

    安装版本为1.17.8. 1.安装Nginx依赖, pcre. openssl. gcc. zlib(推荐使⽤yum源⾃动安装) yum -y install gcc zlib zlib-devel ...

  5. Visual Studio Code 配置C、C++ 文件debug调试环境

    目录 vscode C/C++ Extension Pack 插件安装 vscode windows 端 debug 配置 window MinGW 环境安装 windows 端 C.CPP 单文件 ...

  6. [LeetCode]1221. 分割平衡字符串

    在一个「平衡字符串」中,'L' 和 'R' 字符的数量是相同的. 给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串. 返回可以通过分割得到的平衡字符串的最大数量. 示例 1: 输入:s = ...

  7. [题解]UVA11029 Leading and Trailing

    链接:http://vjudge.net/problem/viewProblem.action?id=19597 描述:求n^k的前三位数字和后三位数字 思路:题目要解决两个问题.后三位数字可以一边求 ...

  8. 【C#多态】as 类型检测(原理分析) ---用于多态检

    as(OpCodes.Castclass)功能:测试对象引用(O 类型)是否为特定类的实例.相当于:expression is type ? (type)expression : (type)null ...

  9. 【代码编译器】vscode 配置详细介绍

    前言:运行环境.net6.0 C#10 安装.NET Core SDK和运行 官网下载地址:https://www.microsoft.com/net/download/core 安装.Net 4.7 ...

  10. readonly 只读字段的初始化值确定|static 字段的初始值确定

    类的初始化顺序 如下: 第一次实例化Son============================ C#编译器缺省将每一个成员变量初始化为他的默认值Son静态字段Son静态构造函数Son字段Fathe ...