P1291 [SHOI2002]百事世界盃之旅
阿新 • • 發佈:2020-10-21
題目描述
你關上電視,心想:假設有 \(n\) 個不同的球星名字,每個名字出現的概率相同,平均需要買幾瓶飲料才能湊齊所有的名字呢?
期望dp 水題 (bushi)。但這輸出也未免太毒瘤了吧。
設 \(f[i]\) 表示當前當前有 \(i\) 個球星的名字的期望。
我們有 \(i\over n\) 的概率抽到的是之前取到的,這時候我們就還需要再抽 \(f[i]\) 次,所以期望就是 \({i\over n}\times (f[i] + 1)\)
還有 \({n-i}\over i\) 的概率抽到的是之前沒有取到的,這時候我們只需要再取 \(f[i-1]\) 次就可以,那麼期望就是 \({{n-i}\over i} \times ({f[i-1] + 1})\)
然後我們就得到了遞推式 \(f[i] = {i\over n}\times (f[i] + 1) + {{n-i}\over i} \times ({f[i-1] + 1})\)
化簡一下可以得到: \(f[i] = f[i-1] + {n\over{n-i}}\)
轉化一下形式變為 \(\displaystyle\sum_{i=1}^{n} {n\over{n-i}}\)
然後在求的的時候注意通分一下就行。
Code
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define int long long int n,mu,zi,ans; int gcd(int a,int b) { if(b == 0) return a; else return gcd(b,a%b); } int wei(int x) { int res = 0; while(x) { res++; x /= 10; } return res; } signed main() { scanf("%lld",&n); mu = 1, zi = n; for(int i = 2; i <= n; i++) { zi = zi * i + n * mu;//通分 mu = mu * i; int res = gcd(mu,zi); mu /= res; zi /= res; } int ans = zi / mu;//求帶數 zi %= mu; if(zi == 0) printf("%lld\n",ans); else { for(int i = 1; i <= wei(ans); i++) printf(" "); printf("%lld\n",zi); printf("%lld",ans); for(int i = 1; i <= wei(mu); i++) printf("-"); printf("\n"); for(int i = 1; i <= wei(ans); i++) printf(" "); printf("%lld\n",mu); } return 0; }