1. 程式人生 > >bzoj 2784 時間流逝 —— 樹上高斯消元

bzoj 2784 時間流逝 —— 樹上高斯消元

getchar() har pac getc amp using 得到 http tmp

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2784

其實轉移是一棵樹,從根到一個點表示一種能量圈狀態,當能量值大於 T 是停止,也就是成為葉子;

點數大約是整數劃分,據說是 1.2e6 左右,可以 dfs;

設 \( d[x] \) 是兒子數,則 \( f[x] = p*(f[fa]+1) + (1-p) \frac{\sum\limits_{v \in son}(f[v]+1)}{d[x]} \)

仍然設 \( f[x] = K[x] * f[fa] + B[x] \),得到 \( K[x] = \frac{d[x]*p}{d[x]-(1-p) \sum A[v] } , B[x] = \frac{(1-p)\sum B[v] + d[x]}{d[x]-(1-p) \sum A[v]} \)

走到葉子停止,而葉子的值本來就是 0,所以直接做即可;

註意根的 \( p \) 不同,直接在根處把 \( p \) 改成 0 即可。

代碼如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef double db;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();}
  while(ch>=
0&&ch<=9)ret=ret*10+ch-0,ch=getchar(); return f?ret:-ret; } int T,n,w[35]; db p; struct N{ db K,B; N(db k=0,db b=0):K(k),B(b) {} }; N dfs(int sum,int d) { if(sum>T)return N(0,0); db ks=0,bs=0,P=(sum==0?0:p); for(int i=1;i<=d;i++) { N tmp=dfs(sum+w[i],i); ks+=tmp.K; bs+=tmp.B; }
return N(d*P/(d-(1-P)*ks),((1-P)*bs+d)/(d-(1-P)*ks)); } int main() { while(~scanf("%lf",&p)) { T=rd(); n=rd(); for(int i=1;i<=n;i++)w[i]=rd(); sort(w+1,w+n+1); printf("%.3f\n",dfs(0,n).B); } return 0; }

bzoj 2784 時間流逝 —— 樹上高斯消元