CF601C Kleofáš and the n-thlon(期望+字首和優化dp)
阿新 • • 發佈:2018-12-01
解題思路
要求這個人的排名,我們可以先求出某個人比他排名靠前的概率,然後再乘上\(m-1\)即為答案。求某個人比他排名靠前可以用\(dp\),設\(f[i][j]\)表示前\(i\)場比賽某人的得分為\(j\)的概率,那麼轉移方程為:\(f[i][j]=\sum\limits_{k=1,k!=x[i]}^(min(m,j)) f[i-1][j-k]\),發現這個複雜度是\(O(n^2*m^2)\)的,無法接受。進一步可以看出轉移形式可以字首和優化,只需要加上字首和後把\(k=x[i]\)這個地方挖去即可。這樣時間複雜度為\(O(n^2*m)\)的,然後用滾動陣列優化空間。
程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> using namespace std; const int MAXN = 105; const int MAXM = 1005; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int n,m,tot,x[MAXN]; double f[2][MAXM*MAXN],ans,sum; int main(){ n=rd(),m=rd();f[0][0]=1.0; for(int i=1;i<=n;i++) x[i]=rd(),tot+=x[i]; for(int i=1;i<=n;i++){ sum=f[(i-1)&1][0]; for(int j=1;j<tot;j++){ f[i&1][j]=sum; if(j>=x[i]) f[i&1][j]-=f[(i-1)&1][j-x[i]]; sum+=f[(i-1)&1][j]; if(j>=m) sum-=f[(i-1)&1][j-m]; f[i&1][j]/=(m-1); } if(i==1) f[0][0]=0; } for(int i=n;i<tot;i++) ans+=f[n&1][i]; printf("%.15lf",ans*(m-1)+1.0); return 0; }