题解 速通

传送门

是出题人没学过语文还是我没学过语文(恼

写出的转移中需要与 \(f_{1, 0}\)\(\min\)
那么二分这个东西的取值即可

p.s. 第五个包数据假了,不满足特殊性质

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define pb push_back
#define ll long long
//#define int long long

int n, lim;
double p[N];
int l[N], r[N];
vector<int> e[N];

namespace task1{
	bool g[110][1010];
	struct line{double k, b; line():k(0),b(0){} line(double x, double y):k(x),b(y){}}f[110][1010];
	inline line operator + (line a, line b) {return {a.k+b.k, a.b+b.b};}
	inline line operator * (line a, double t) {return {a.k*t, a.b*t};}
	inline bool isable(int i, int j) {return j<=lim?g[i][j]:0;}
	void dfs1(int u) {
		if (!e[u].size()) {
			for (int i=0; i<=lim; ++i) g[u][i]=1;
			return ;
		}
		for (auto v:e[u]) dfs1(v);
		for (int j=0; j<=lim; ++j)
			for (auto v:e[u]) if (p[v]>0)
				g[u][j]|=isable(v, j+l[v]);
	}
	void dfs2(int u) {
		// cout<<"dfs2: "<<u<<endl;
		for (auto v:e[u]) dfs2(v);
		for (int j=0; j<=lim; ++j) {
			// cout<<"j: "<<j<<endl;
			for (int k=l[u]; k<=r[u]; ++k) {
				// cout<<"k: "<<k<<endl;
				if (isable(u, j+k)) {
					line sum;
					for (auto v:e[u]) sum=sum+f[v][j+k]*p[v];
					sum=sum+line(0, k);
					// cout<<"("<<sum.k<<' '<<sum.b<<") "<<endl;
					f[u][j]=f[u][j]+sum;
				}
				else f[u][j]=f[u][j]+line(1, k);
			}
			f[u][j]=f[u][j]*(1.0/(r[u]-l[u]+1.0));
		}
	}
	void solve() {
		dfs1(1); dfs2(1);
		// cout<<"("<<f[1][0].k<<' '<<f[1][0].b<<") "<<endl;
		if (!isable(1, 0)) puts("Remake");
		else {
			double ans=f[1][0].b/(1-f[1][0].k);
			if (ans>=1e9) puts("Remake");
			else printf("%.10lf\n", ans);
		}
	}
}

namespace task{
	double f[110][2010];
	void solve() {
		double l=0, r=1e9+1, mid;
		for (int t=1; t<=60; ++t) {
			mid=(l+r)/2;
			// cout<<"mid: "<<mid<<endl;
			memset(f, 0x43, sizeof(f));
			for (int i=n; i; --i) {
				// cout<<"i: "<<i<<endl;
				for (int j=0; j<=lim; ++j) {
					// cout<<"j: "<<j<<endl;
					double sum=0;
					for (int k=::l[i]; k<=::r[i]; ++k) {
						// cout<<"k: "<<k<<endl;
						if (j+k<=lim) {
							double tem=0;
							for (auto v:e[i]) tem+=p[v]*f[v][j+k];
							// cout<<"tem: "<<tem<<endl;
							sum+=min(tem, mid)+k;
						}
						else sum+=mid+k;
					}
					f[i][j]=sum/(::r[i]-::l[i]+1);
				}
			}
			if (f[1][0]>mid) l=mid;
			else r=mid;
		}
		if (l>=1e9) puts("Remake");
		else printf("%.10lf\n", l);
	}
}

signed main()
{
	freopen("isaac.in", "r", stdin);
	freopen("isaac.out", "w", stdout);

	scanf("%d%d", &n, &lim);
	for (int i=1; i<=n; ++i) scanf("%d%d", &l[i], &r[i]);
	for (int i=2,f; i<=n; ++i) scanf("%d%lf", &f, &p[i]), e[f].pb(i);
	// task1::solve();
	task::solve();

	return 0;
}
posted @ 2022-04-05 18:14  Administrator-09  阅读(3)  评论(0编辑  收藏  举报