概率论 - Keeping Rabbits - CCPC 2019 哈尔滨
题意:
给 定 n 个 数 w 1 , w 2 , . . . w n , 每 天 都 会 有 一 个 数 增 加 1 , 给定n个数w_1,w_2,...w_n,每天都会有一个数增加1, 给定n个数w1,w2,...wn,每天都会有一个数增加1,
第 i 个 数 增 加 1 的 概 率 为 : 第i个数增加1的概率为: 第i个数增加1的概率为:
w i ∑ j = 1 n w j \frac{w_i}{\sum_{j=1}^nw_j} ∑j=1nwjwi
求 k 天 后 , 各 个 数 大 小 的 期 望 是 多 少 。 求k天后,各个数大小的期望是多少。 求k天后,各个数大小的期望是多少。
Input
The input contains multiple cases. The first line of the input contains a single integer T (1≤T≤105), the number of cases.
For each case, the first line of the input contains two integers n and k (1≤n≤105,1≤k≤109). The second line contains n integers w1,w2,…,wn (1≤i≤n,1≤wi≤109).
It’s guaranteed that the sum of n over all cases doesn’t exceed 106.
Output
For each case, print a single line containing n space-separated real numbers, where the i-th (1≤i≤n) number should be equal to the expected weight of the i-th rabbit after k days.
Your answer will be considered correct if the absolute or relative error does not exceed 10−4.
Example
input
3
1 1
2
2 2
1 3
3 2
1 1 1
output
3.00000000
1.50000000 4.50000000
1.66666667 1.66666667 1.66666667
1.5 s, 512 MB
分析:
看 到 这 个 数 据 范 围 , 显 然 我 们 是 要 做 到 O ( n l o g ) 或 者 O ( n ) 的 级 别 。 看到这个数据范围,显然我们是要做到O(nlog)或者O(n)的级别。 看到这个数据范围,显然我们是要做到O(nlog)或者O(n)的级别。
我 们 先 尝 试 表 示 第 k 天 , 第 i 个 数 的 期 望 值 E ( w k ( i ) ) : 我们先尝试表示第k天,第i个数的期望值E(w_k(i)): 我们先尝试表示第k天,第i个数的期望值E(wk(i)):
记 第 k 天 所 有 数 的 和 s u m ( k ) = ∑ i = 1 n w k ( i ) , 第 i 个 数 增 1 的 概 率 为 P k ( i ) = w k − 1 ( i ) s u m ( k − 1 ) , 记第k天所有数的和sum(k)=\sum_{i=1}^nw_k(i),第i个数增1的概率为P_k(i)=\frac{w_{k-1}(i)}{sum(k-1)}, 记第k天所有数的和sum(k)=∑i=1nwk(i),第i个数增1的概率为Pk(i)=sum(k−1)wk−1(i),
容 易 发 现 : 容易发现: 容易发现:
s u m ( k ) = s u m ( k − 1 ) + 1 , k ≥ 1 sum(k)=sum(k-1)+1,k\ge 1 sum(k)=sum(k−1)+1,k≥1
则 : 则: 则:
E ( w k ( i ) ) = P k ( i ) × [ w k − 1 ( i ) + 1 ] + [ 1 − P k ( i ) ] × w k − 1 ( i ) = P k ( i ) + w k − 1 ( i ) = w k − 1 ( i ) × ( 1 + 1 s u m ( k − 1 ) ) E(w_k(i))=P_k(i)×[w_{k-1}(i)+1]+[1-P_k(i)]×w_{k-1}(i)=\\\ \\P_k(i)+w_{k-1}(i)=w_{k-1}(i)×(1+\frac{1}{sum(k-1)}) E(wk(i))=Pk(i)×[wk−1(i)+1]+[1−Pk(i)]×wk−1(i)= Pk(i)+wk−1(i)=wk−1(i)×(1+sum(k−1)1)
继 续 推 导 : 继续推导: 继续推导:
E ( w k ( i ) ) = w k − 1 ( i ) × ( 1 + 1 s u m ( k − 1 ) ) = E ( w k − 1 ( i ) ) × ( 1 + 1 s u m ( k − 1 ) ) = w k − 2 ( i ) × ( 1 + 1 s u m ( k − 1 ) ) × ( 1 + 1 s u m ( k − 2 ) ) = . . . = w 1 ( i ) × ∏ i = 1 k ( 1 + 1 s u m ( i ) ) E(w_k(i))=w_{k-1}(i)×(1+\frac{1}{sum(k-1)}) = E(w_{k-1}(i))×(1+\frac{1}{sum(k-1)})=\\\ \\w_{k-2}(i)×(1+\frac{1}{sum(k-1)})×(1+\frac{1}{sum(k-2)})=...=\\\ \\ w_1(i)× \prod_{i=1}^k(1+\frac{1}{sum(i)}) E(wk(i))=wk−1(i)×(1+sum(k−1)1)=E(wk−1(i))×(1+sum(k−1)1)= wk−2(i)×(1+sum(k−1)1)×(1+sum(k−2)1)=...= w1(i)×i=1∏k(1+sum(i)1)
到 这 里 , 乍 一 看 , 我 们 需 要 处 理 一 个 前 缀 积 , 但 是 k ≤ 1 0 9 , 因 此 我 们 需 要 发 掘 其 他 性 质 。 到这里,乍一看,我们需要处理一个前缀积,但是k\le 10^9,因此我们需要发掘其他性质。 到这里,乍一看,我们需要处理一个前缀积,但是k≤109,因此我们需要发掘其他性质。
事 实 上 , 因 为 s u m ( i ) = s u m ( i − 1 ) + 1 , 所 以 : 事实上,因为sum(i)=sum(i-1)+1,所以: 事实上,因为sum(i)=sum(i−1)+1,所以:
∏ i = 1 k ( 1 + 1 s u m ( i ) ) = ∏ i = 1 k ( s u m ( i ) + 1 s u m ( i ) ) = s u m ( k ) + 1 s u m ( 1 ) = s u m ( 1 ) + k s u m ( 1 ) \prod_{i=1}^k(1+\frac{1}{sum(i)})=\prod_{i=1}^k(\frac{sum(i)+1}{sum(i)})=\frac{sum(k)+1}{sum(1)}=\frac{sum(1)+k}{sum(1)} i=1∏k(1+sum(i)1)=i=1∏k(sum(i)sum(i)+1)=sum(1)sum(k)+1=sum(1)sum(1)+k
因 此 , 最 终 答 案 : 因此,最终答案: 因此,最终答案:
E ( w k ( i ) ) = w 1 ( i ) × s u m ( 1 ) + k s u m ( 1 ) E(w_k(i)) = w_1(i)×\frac{sum(1)+k}{sum(1)} E(wk(i))=w1(i)×sum(1)sum(1)+k
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N = 1e5+10;
int T;
int n, k;
double w[N];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n, &k);
double sum = 0;
for(int i=0;i<n;i++)
{
scanf("%lf",&w[i]);
sum += w[i];
}
for(int i=0;i<n;i++) printf("%f ",w[i]*(1+k/sum));
puts("");
}
return 0;
}