题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2784
一个状态可以加很多个能量圈,但减少能量圈的情况只有一种。所以可以用树来刻画。
然后就变成树上高斯消元的套路了。注意根节点的 P 等于 0 。
发现不是要求 dp[ 1 ] 就必须在那个式子里设出 a*dp[ 1 ] 之类的。
据说树上的点大概有 1.2*106 个。大概就是贝尔数吧。
#include<cstdio> #include<cstring> #include<algorithm> #define mkp make_pair #define fir first #define sec second #define db double using namespace std; const int N=35; int n,m,w[N];db P; pair<db,db> dfs(int lm,int s) { db ta=0,tb=0;if(s>n)return mkp(0,0); for(int i=1;i<=lm;i++) { pair<db,db> v=dfs(i,s+w[i]); ta+=v.fir; tb+=v.sec; } if(!s)P=0; ta=1-(1-P)/lm*ta; ta=1/ta; tb=((1-P)/lm*tb+1)*ta; ta=P*ta; return mkp(ta,tb); } int main() { while(scanf("%lf",&P)==1) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)scanf("%d",&w[i]); sort(w+1,w+m+1);// printf("%.3f ",dfs(m,0).sec); } return 0; }