[理综考试]
一场理综考试中有n个考生,编号为1~n,第i个考生的得分是[li,ri]中随机的一个实数
求每个考生得到每个排名的概率
Input
8
0 2
1 3
2 4
3 5
4 6
5 7
6 8
7 9
Output
0 0 0 0 0 0 0.125 0.875
0 0 0 0 0 0.125 0.75 0.125
0 0 0 0 0.125 0.75 0.125 0
0 0 0 0.125 0.75 0.125 0 0
0 0 0.125 0.75 0.125 0 0 0
0 0.125 0.75 0.125 0 0 0 0
0.125 0.75 0.125 0 0 0 0 0
0.875 0.125 0 0 0 0 0 0
绝对误差不超过10^-6算作正确
Sol:
考虑将区间离散,得到这个人分散在一些小区间以及在每个小区间的概率
枚举每一个人以及他的所属区间,得到一个概率P
因为可能会有重叠,所以设f[i][j]代表有i个人比这个人名次靠后,j个人和他在一个区间内的概率
转移见代码,注意概率计算
那么枚举i和j,这个人在[i+1,i+j+1]的排名的概率为f[i][j] * p * 1/(j+1)
累加进答案。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define maxn 100 #define eps 1e-12 using namespace std; int n, L[maxn], R[maxn], h[maxn*2], cnt, ll, rr; double g[maxn], f[maxn][maxn]; double getwin(int i){ if(R[i] <= rr)return 0; if(L[i] >= rr)return 1; return (double)(R[i]-rr)/(R[i]-L[i]); } double getlose(int i){ if(R[i] <= ll)return 1; if(L[i] >= ll)return 0; return (double)(ll-L[i])/(R[i]-L[i]); } void solve(int nw, int k){ ll = h[k], rr = h[k+1]; double p = (double)(rr-ll) / (R[nw]-L[nw]); memset(f, 0, sizeof f); f[0][0] = 1; for(int i = 1; i <= n; i ++){ if(i == nw)continue; double win = getwin(i), lose = getlose(i), equal = 1.0-win-lose; for(int j = i-1; j >= 0; j --){ for(int k = i-1-j; k >= 0; k --)if(f[j][k] > eps){ f[j+1][k] += lose * f[j][k]; f[j][k+1] += equal * f[j][k]; f[j][k] = win * f[j][k]; } } } for(int i = 0; i < n; i ++) for(int j = 0; j < n-i; j ++) for(int k = 0; k <= j; k ++) g[i+k] += f[i][j]*p/(j+1); } int main(){ freopen("gg.in", "r", stdin); freopen("gg.out", "w", stdout); scanf("%d", &n); for(int i = 1; i <= n; i ++){ scanf("%d%d", &L[i], &R[i]); h[++ cnt] = L[i], h[++ cnt] = R[i]; } sort(h+1, h+1+cnt); cnt = unique(h+1, h+1+cnt)-h-1; //for(int i = 1; i <= cnt; i ++)cout << h[i] << ' ';cout << endl; for(int i = 1; i <= n; i ++){ memset(g, 0, sizeof g); int l = lower_bound(h+1, h+1+cnt, L[i]) - h; int r = lower_bound(h+1, h+1+cnt, R[i]) - h; for(int j = l; j < r; j ++)solve(i, j); for(int j = n-1; ~ j; j --) printf("%.10lf ", g[j]); puts(""); } return 0; }
给时光以生命,而不是给生命以时光。