一、题目
二、解法
首先
k
x
=
x
1
/
k
k\sqrt{x}=x^{1/k}
kx=x1/k,对于这种指数的问题我们可以用
ln
\ln
ln把它转化为系数,同时取
ln
\ln
ln:
ln
a
n
s
=
1
c
∑
i
=
1
c
ln
v
[
i
]
\ln ans=\frac{1}{c}\sum_{i=1}^c \ln{v[i]}
lnans=c1i=1∑clnv[i]然后上式很像
ln
\ln
ln平均值的最大值,我们可以二分答案,那么我们只需要判断:
∑
i
=
1
c
v
[
i
]
−
m
i
d
>
0
\sum_{i=1}^c v[i]-mid>0
i=1∑cv[i]−mid>0所以我们求出上式的最大值即可,这一部分可以直接套
AC
\text{AC}
AC自动机
+
d
p
+dp
+dp,设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为前
i
i
i个字符匹配到
j
j
j的最大值,暴力跳转移即可。最后的答案就是最优值路径的还原,
d
p
dp
dp时注意记录一下就行了。
时间复杂度 O ( 10 × n m × log ( ln 1 e 9 ) ) O(10\times nm\times \log(\ln 1e9)) O(10×nm×log(ln1e9)),贴个代码。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#define eps 1e-6
#define inf 1e30
using namespace std;
const int M = 1505;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,cnt,fail[M],c[M][10],num[M],g[M][M][2];
double sum[M],f[M][M];char t[M],s[M],str[M];
void ins()
{
int p=0,len=strlen(s);
for(int i=0;i<len;i++)
{
int v=s[i]-'0';
if(!c[p][v]) c[p][v]=++cnt;
p=c[p][v];
}
num[p]++;
sum[p]+=log((double)read());
}
void build()
{
queue<int> q;
for(int i=0;i<10;i++) if(c[0][i]) q.push(c[0][i]);
while(!q.empty())
{
int t=q.front();
q.pop();
sum[t]+=sum[fail[t]];
num[t]+=num[fail[t]];
for(int i=0;i<10;i++)
if(c[t][i]) fail[c[t][i]]=c[fail[t]][i],q.push(c[t][i]);
else c[t][i]=c[fail[t]][i];
}
}
double dp(double v)
{
for(int i=0;i<=cnt;i++)
sum[i]-=v*num[i];
for(int i=0;i<=n;i++)
for(int j=0;j<=cnt;j++)
f[i][j]=-inf;
f[0][0]=0;
for(int i=0;i<n;i++)
for(int j=0;j<=cnt;j++)
{
if(f[i][j]==-inf) continue;
if(t[i]=='.')
{
for(int k=0;k<10;k++)
{
int to=c[j][k];
if(f[i+1][to]<f[i][j]+sum[to])
{
f[i+1][to]=f[i][j]+sum[to];
g[i+1][to][0]=j;
g[i+1][to][1]=k;
}
}
}
else
{
int to=c[j][t[i]-'0'];
if(f[i+1][to]<f[i][j]+sum[to])
{
f[i+1][to]=f[i][j]+sum[to];
g[i+1][to][0]=j;
g[i+1][to][1]=t[i]-'0';
}
}
}
for(int i=0;i<=cnt;i++) sum[i]+=num[i]*v;
int tmp=0;
for(int j=1;j<=cnt;j++)
if(f[n][j]>f[n][tmp])
tmp=j;
for(int i=n,p=tmp;i>=1;i--)
{
str[i-1]=g[i][p][1]+48;
p=g[i][p][0];
}
return f[n][tmp];
}
int main()
{
n=read();m=read();
scanf("%s",t);
while(m--)
{
scanf("%s",s);
ins();
}
build();
double l=0,r=log(1e9+5),mid,ans=0;
while(r-l>eps)
{
mid=(l+r)/2;
if(dp(mid)>0) ans=mid,l=mid;
else r=mid;
}
dp(ans);
printf("%s",str);
}