Description
學校的運動會開始了,體能很菜的小可可沒報任何比賽項目,於是和同學們玩一個十分無聊的遊戲。
遊戲在一個由nn個方格組成的正方形棋盤上進行,首先在每個方格上均勻隨機地填入1到m之間的正整數(每個方格填的數均不同),然後小可可均勻隨機地選出k個1到m的數字(可能選的數不在棋盤上),把它們出現在棋盤上的方格塗黑,設有R行被整行塗黑,有C列被整列塗黑,小可可便可以得到2^(R+C)分。
現在小可可想知道他的期望得分是多少,你能幫助他嗎?
Input
第一行包含三個正整數n,m,k。
Output
僅一行包含一個實數,爲期望得分,如果答案>10^99,就輸出 1099,輸出被認爲正確當且僅當你的輸出與標準輸出的相對誤差不超過10-6。
Data Constraint
對於30%的數據,2≤n≤5,m≤10;
對於60%的數據,2≤n≤10,m≤200;
對於100%的數據,2≤n≤300, nn≤m≤100000, n≤k≤m。
Solution
算法一:
m≤10,實際上 n≤3,於是可以暴力枚舉所有的填法和選法。
期望得分:30 分
算法二:
設行集合R和列集合C,|R| = r, |C| = c而這些行被塗黑的概率爲,
而答案還可以表示爲
這裏這個Pr,c也十分好求,爲
這裏 t=n(r+c)-rc 爲整行、列填黑的格子個數。
時間複雜度O(n^2),期望得分100分
Code
#include <cstdio>
int n, m, k;
double ans;
double f[407], g[100007];
int main()
{
ans = 0;
scanf("%d%d%d", &n, &m, &k);
f[0] = g[0] = 1;
for (int i = 1; i <= n; ++ i) f[i] = f[i - 1] / i * (n - i + 1);
for (int i = 1; i <= m; ++ i) g[i] = g[i - 1] / (m - i + 1) * (k - i + 1);
for (int i = 0; i <= n; ++ i)
{
for (int j = 0; j <= n; ++ j)
{
int t = (i + j) * n - i * j;
if (t > k) continue;
ans += f[i] * f[j] * g[t];
}
}
printf("%0.12f\n", (ans > 1e99) ? (1e99) : (ans));
return 0;
}