BZOJ2784: [JLOI2012]时间流逝
BZOJ2784: [JLOI2012]时间流逝
https://lydsy.com/JudgeOnline/problem.php?id=2784
分析:
- 挺有意思的一道题。
- 注意到状态数是\(P(T)\),由于\(T\le 50\),这个总数不会很大。
- 于是我们暴力搜状态再\(dp\)。
- 由于\(dp\)转移有从儿子到父亲这样的,我们用树上高斯消元就行了。
- 特别需要注意的是每次随机产生的能量圈是在能够吃到的范围内随机的。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
#define N 1500050
typedef double f2;
int n,T;
f2 P,K[N],B[N],tmp;
int a[105],cnt;
int dfs(int pos,int sum) {
if(sum>T) return 0;
int x=++cnt;
int i;
K[x]=P; B[x]=x>1?P:0; f2 lhs=1;
f2 tmp=(1-(x>1?P:0))/pos;
for(i=1;i<=pos;i++) {
int t=dfs(i,sum+a[i]);
lhs-=K[t]*tmp;
B[x]+=(B[t]+1)*tmp;
}
K[x]/=lhs; B[x]/=lhs;
return x;
}
int main() {
while(scanf("%lf%d%d",&P,&T,&n)!=EOF) {
cnt=0;
int i;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
printf("%.3f\n",B[dfs(n,0)]);
}
}