1. 程式人生 > >🔺 Garbage Remembering Exam UVA - 11637()

🔺 Garbage Remembering Exam UVA - 11637()

namespace %d ... double iss += sin https water

題目大意:給你N個單詞,有兩種方法隨機排列,一種隨機排成一行,另一種隨機排成一圈,當兩個單詞之間的距離在兩種排列中都嚴格小於K時,則這兩個單詞構成無效單詞,問無效單詞的期望。 解題思路:首先對於一排單詞的每個單詞,取出距離它為K的單詞,然後把取出的單詞放到環形序列的這個單詞的兩邊 如果我們能分別算出1-n的有效概率,那麽就等於算出了無效概率

技術分享圖片

其中 x為當前單詞的左右距離為k的單詞的個數, 分子是把一排單詞中一個單詞的有效距離的單詞取出來全排列到環形的無效距離內,然後剩余的單詞全排列;

考慮到排列與組合數據過大,用 exp()函數,其中log(N!)=log(N)+log(N-1)+...+log(1);

需要註意 用long double能過。。。

代碼如下:

沒大弄明白為什麽n-1-x < 2*k 的時候不考慮

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 100005
long double temp[N];
int n,k;
double solve()
{
    if(n==1) return 0;//只有一個單詞,無效為0
    else if(2*k+1>=n) return
n;//如果圈中的一個單詞從左邊或右邊距離都小於K,則該單詞無效,所有單詞等效 double ret=0; for(int i=1;i<=n;i++) { int x=min(k,i-1)+min(k,n-i);//一個單詞左右k範圍內的單詞個數 if(n-1-x-2*k>=0) { ret+=exp(temp[n-1-x]+temp[n-1-2*k]-temp[n-1]-temp[n-1-x-2*k]); } // else // ret += exp(temp[2*k] - temp[2*k-n+1+x] + temp[x] - temp[n-1]);
} return n-ret; } int main() { temp[0]=0; for(int i=1;i<N;i++) temp[i]=temp[i-1]+log((long double)i); int cas=1; while(scanf("%d%d",&n,&k)) { if(n==0&&k==0) break; printf("Case %d: %.4lf\n",cas++,solve()); } return 0; }

🔺 Garbage Remembering Exam UVA - 11637()