1. 程式人生 > 實用技巧 >2019 ACM/ICPC North America Qualifier G.Research Productivity Index(概率期望dp)

2019 ACM/ICPC North America Qualifier G.Research Productivity Index(概率期望dp)

https://open.kattis.com/problems/researchproductivityindex

這道題是考場上沒寫出來的一道題,今年看看感覺簡單到不像話,當時自己對於dp沒有什麼概念,所以導致考場只能空流淚

首先問期望,肯定就要確定概率。看到這個

就知道肯定一塊求是不太好寫的,先求上面,上面求發表的期望,那麼對於期望我們有e(x) = Σxipi

這裡p知道了但是xi不知道,那麼我們根據題目描述我們有一個分子一個分母,分子是發表的次數,分母是論文數,首先對於任何j篇論文發表了 i 篇來講,都無外乎兩種情況,一個是上一篇就發表了這麼多,這一篇雖然多了一篇論文但沒有對論文發表數產生貢獻,那麼這種情況概率 1- p,第二種情況就是這種發表了,這種情況概率是p

那麼狀態轉移方程顯然就有

dp[i][j] = (a[i]) * dp[i - 1][j - 1] + (1 - a[i]) * dp[i - 1][j];//新增沒發表和發表

我們要求最大,所以要先從機率大的開始發表,sort一遍(我腦殘還降序排了,趕緊reverse),然後不發表的次數initialize一下,求出來上面那一撥東西之後就再轉化成發表成功次數,pow函式求解,列舉,看哪個大就可了,真的超級簡單一個dp,md去年的沒做出來真是恥辱啊啊啊啊

#include <bits/stdc++.h>
using namespace std;
#define limit (100 + 5)//
防止溢位 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步兩步 #define EPS 1e-6 #define FASTIO ios::sync_with_stdio(false);cin.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a,b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define
MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\acm_01\\dabiao.txt", "wt", stdout) #define debug(x) cout<<x<<endl typedef long long ll; typedef unsigned long long ull; inline ll read(){ ll sign = 1, x = 0;char s = getchar(); while(s > '9' || s < '0' ){if(s == '-')sign = -1;s = getchar();} while(s >= '0' && s <= '9'){x = (x << 3) + (x << 1) + s - '0';s = getchar();} return x * sign; }//快讀 void write(ll x){ if(x < 0) putchar('-'),x = -x; if(x / 10) write(x / 10); putchar(x % 10 + '0'); } int n; double a[limit]; double dp[limit][limit];//代表在i篇論文發表了j篇, int main() { #ifdef LOCAL FOPEN; #endif n = read(); rep(i ,1,n){ a[i] = (1.0 * read()) / 100; } sort(a + 1, a + 1 + n); reverse(a + 1, a + 1 + n); dp[0][0] = 1; dp[1][1] = a[1]; dp[1][0] = 1 - a[1]; rep(i ,2,n)dp[i][0] = dp[i - 1][0] * (1 - a[i]), dp[i][i] = dp[i - 1][ i - 1] * a[i]; rep(i ,1,n){ rep(j, 1,i){ dp[i][j] = (a[i]) * dp[i - 1][j - 1] + (1 - a[i]) * dp[i - 1][j];//新增沒發表和發表 } } double ans = 0; rep(i ,1,n){ double tmp = 0; rep(j, 1,i){ tmp += dp[i][j] * pow(j,1.0 * j / (1.0 * i)); } ans = max(tmp, ans); } cout<<fixed<<setprecision(6)<<ans<<endl; return 0; }