ICPC 焦作 Sequence
https://nanti.jisuanke.com/t/31713
題目是給定
從 中等概率取 個數字,組成一個非遞減序列,記 爲 出現的次數 .
計算下式期望
顯然,順序不重要,考慮計算所有可能的總情況的數量,即方程:
對應的總答案數。
這個方程答案數量爲(對m個1進行插入n-1個擋板,擋板之間的1的個數對應f):
記 爲將 拆分成 個數字,最大數字爲 的所有排列。
那麼我們將這 個數隨機分配給 ,未分配的 的是 ,那麼分配方案顯然是:
記: 爲 的概率。
下面考慮計算 數組。
顯然, 可以分兩部貢獻:
第一部分,最後一個數字拆分小於x,那麼之後的拆分必須出現一個x:
記 表示拆分最大數字不超過 的所有排列:
那麼第二部分貢獻爲:
對於 有:
考慮壓縮 ,並遞推過程中記錄。
這樣就有了概率密度函數。
則答案爲:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define MAXN 252
using namespace std;
long double C;
double dp[MAXN][MAXN][2];
double Sd[MAXN][MAXN][2];
double Sa[MAXN][MAXN][2];
double A[MAXN][MAXN][2];
double B[MAXN][MAXN];
int main()
{
int n, m;
while (scanf("%d %d", &m, &n) == 2)
{
memset(dp, 0, sizeof dp);
memset(Sa, 0, sizeof Sa);
memset(Sd, 0, sizeof Sd);
memset(A, 0, sizeof A);
memset(B, 0, sizeof B);
for (int i = 0;i <= m;i++)A[0][i][0] = 1;
for (int i = 0;i <= m;i++)
for (int j = 0;j <= m;j++)Sa[i][j][0] = 1;
for (int i = 0;i <= m;i++)Sd[i][0][0] = 1;
dp[0][0][0] = 1;
bool ansf = false;
for (int t = 1;t <= m;t++, ansf = !ansf)
{
for (int x = 0;x <= m;x++)A[0][x][!ansf] = 0;
for (int i = 0;i <= m;i++)
for (int x = 0;x <= m;x++)Sd[i][x][!ansf] = Sa[i][x][!ansf] = 0;
for (int i = 1;i <= m;i++)
{
for (int x = 1;x <=m;x++)
{
if (x > i)
{
dp[i][x][!ansf] = 0;
A[i][x][!ansf] = A[i][i][!ansf];
Sa[i][x][!ansf] = Sa[i - 1][x][!ansf] + A[i][x][!ansf];
Sd[i][x][!ansf] = Sd[i - 1][x][!ansf];
continue;
}
A[i][x][!ansf] = Sa[i - 1][x][ansf];
if (i > x)A[i][x][!ansf] -= Sa[i - x - 1][x][ansf];
dp[i][x][!ansf] = A[i - x][x][ansf] + Sd[i - 1][x][ansf] - Sd[i - x][x][ansf];
Sd[i][x][!ansf] = Sd[i - 1][x][!ansf] + dp[i][x][!ansf];
Sa[i][x][!ansf] = Sa[i - 1][x][!ansf] + A[i][x][!ansf];
}
if (i == m)
for (int x = 1;x <= m;x++) B[x][t] = dp[m][x][!ansf];
}
}
C = 1;
long double ans = 0;
for (int k = 1;k <= m;k++)C *= ((long double)k) / ((long double)n - 1 + k);
for (int t = 1;t <= m&&t <= n;t++)
{
C *= (long double)(n - t + 1) / (long double)t;
for (int x = 1;x <= m;x++)
{
//if (B[x][t])printf("%lld\n", B[x][t]);
ans += x*B[x][t] * C;
}
}
printf("%.4f\n", (double)ans);
}
return 0;
}