題意:隨機的給你k個數,範圍1~n,問你使得區間[1, n]的每個數都出現至少兩次的期望次數。
思路:f[i][j] 表示有i個數需要出現一次,j個數需要出現兩次,那麼:
f[i][j] = i / n * f[i - 1][j] + j / n * f[i + 1][j - 1] + (n - i - j) / n * f[i][j] + 1
f[i][j] = i / (i + j) * f[i - 1][j] + j / (i + j) * f[i + 1][j - 1] + n / (i + j)
這題多樣例要記憶化一下否則會超時,但是n不同會導致結果不同,所以把n提出來
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e3 + 10;
double f[maxn][maxn];
int vis[maxn];
int n;
double calc(int i, int j)
{
if(i == 0 && j == 0) return 0;
if(f[i][j]) return f[i][j];
f[i][j] = 1;
if(i > 0) f[i][j] += i * calc(i - 1, j);
if(j > 0) f[i][j] += j * calc(i + 1, j - 1);
f[i][j] = f[i][j] / (i + j);
return f[i][j];
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
memset(vis, 0, sizeof(vis));
int k, x;
scanf("%d%d", &n, &k);
for(int i = 1; i <= k; ++i) scanf("%d", &x), vis[x]++;
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= n; ++i)
{
if(vis[i] == 1) cnt1++;
else if(vis[i] == 0) cnt2++;
}
printf("%.10f\n", n * calc(cnt1, cnt2));
}
return 0;
}