luogu P3239 [HNOI2015]亞瑟王
阿新 • • 發佈:2022-03-17
題面傳送門
因為每次有一輪打出一發就不打了的限制所以不能直接期望去算。
考慮一個點\(i\)之前如果打出了\(j\)個技能,無論這\(j\)個技能是啥,\(i\)這個點都會被打\(r-j\)次,這啟發我們設\(f_{i,j}\)為\(1\)到\(i\)點打出\(j\)次的概率。
有了這個就可以算每個點被打出的期望了,根據期望的線性性直接乘傷害加起來就好了。
時間複雜度\(O(Tnr)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define re register #define RI re int #define ll long long #define db double #define lb long db #define N (220+5) #define M (40+5) #define mod 1000000007 #define Mod (mod-1) #define eps (1e-9) #define U unsigned int #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) #define Mc(x,y) memcpy(x,y,sizeof(x)) #define d(x,y) (n*(x-1)+(y)) #define R(n) (rand()*rand()%(n)+1) #define Pc(x) putchar(x) #define LB lower_bound #define UB upper_bound #define PB push_back using namespace std; int n,m,T,A[N+5],Ne,La;db Ans,P[N+5],dp[2][N],Po[N+5]; I void Solve(){ RI i,j;scanf("%d%d",&n,&m);for(i=1;i<=n;i++) scanf("%lf%d",&P[i],&A[i]); Ans=0;Me(dp,0);dp[0][0]=1;for(i=1;i<=n;i++){ Ne=i&1;La=Ne^1;Me(dp[Ne],0);for(Po[0]=j=1;j<=m;j++) Po[j]=Po[j-1]*(1-P[i]); for(j=0;j<=m;j++) dp[Ne][j]+=dp[La][j]*Po[m-j],dp[Ne][j+1]+=dp[La][j]*(1-Po[m-j]),Ans+=A[i]*dp[La][j]*(1-Po[m-j]); }printf("%.10lf\n",Ans); } int main(){ freopen("1.in","r",stdin); scanf("%d",&T);while(T--) Solve(); }