CF1801F 题解
mod998244353 · · 题解
看到积式,我们自然能想到用 dp 来解决此类问题。
设
自然可以通过枚举
令
初始状态为:
直接转移是
可以发现,第二维的值是由
向上取整有一个性质:
而且这个式子可以嵌套:
这样我们就可以把向上取整转化为向下取整了,用类似杜教筛的转移方式就可以得到
警钟长鸣:递归写法有可能被卡常,我考场上就被卡了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=105,N=7005;
int n,k,a[MAXN],v[N],m,id[10000001];
bool vis[MAXN][N];
double f[MAXN][N];
int main() {
scanf("%d%d",&n,&k);
for(int i=1; i<=n; ++i)
scanf("%d",&a[i]);
if(k==1) {//记得特判k=1
double ans=1.0;
printf("%.20lf\n",ans);
return 0;
}
for(int l=1,r; l<k; l=r+1) {
r=(k-1)/((k-1)/l);
v[++m]=(k-1)/l;
id[v[m]]=m;
}
v[++m]=0,id[0]=m;//不要忘记还有1
f[0][1]=1;
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
if(f[i-1][j]) {
for(int l=1,r; l<=v[j]; l=r+1) {
r=v[j]/(v[j]/l);
f[i][id[v[j]/r]]=max(f[i][id[v[j]/r]],(a[i]/l)/(double)a[i]*f[i-1][j]);
}
f[i][m]=max(f[i][m],(a[i]/(v[j]+1))/(double)a[i]*f[i-1][j]);
}
printf("%.15lf\n",f[n][m]*k);
return 0;
}