ACM Qingdao Onsite 2016 C
阿新 • • 發佈:2018-12-13
思路來源
題意
你有一根餅乾棒,給定初始L和長度d,
若L≤d,就不啃了,期望次數為0。
否則,隨機選擇L上一個位置,把餅乾棒啃成左右兩半,
把左一半吃掉,若右一半長度大於d就重複該操作,直至啃完之後的右段小於d。
問:啃的期望次數。
題解
本來可以考慮概率dp,
若有一個最小步長1可以限制的話,概率dp就可以解決了。
設i可以向i-1,i-2,…d,…,1轉移(由於一定啃成兩半,故不能向i和0轉移)
記dp[i]為長度為i的期望次數,
則i的期望為
這裡,由於五位小數,所以將小數*1e5離散化為整數,概率dp會精度不夠
所以,我們考慮連續的情形,幾何概型,
這就變成了一道微分方程的題目QAQ
記f[x]為長度為x的期望次數,可取小數,
①
求導,有
即,
即
①式中,x趨於d+時,f[x]趨於1,
即,
綜上有,
程式碼
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <functional> const double INF=0x3f3f3f3f; const int maxn=1e5+10; const int mod=1e9+7; const int MOD=998244353; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<double,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; int main() { int n; sci(n); rep(i,0,n-1) { double d,l; sclf(l),sclf(d); if(l<=d+eps)puts("0.000000"); else printf("%.6lf\n",log(l)-log(d)+1); } return 0; }