CodeForces - 248E - E. Piglet's Birthday(组合数+概率dp)

题目链接:http://codeforces.com/problemset/problem/248/E

E. Piglet's Birthday

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Piglet has got a birthday today. His friend Winnie the Pooh wants to make the best present for him — a honey pot. Of course Winnie realizes that he won't manage to get the full pot to Piglet. In fact, he is likely to eat all the honey from the pot. And as soon as Winnie planned a snack on is way, the pot should initially have as much honey as possible.

The day before Winnie the Pooh replenished his honey stocks. Winnie-the-Pooh has n shelves at home, each shelf contains some, perhaps zero number of honey pots. During the day Winnie came to the honey shelves q times; on the i-th time he came to some shelf ui, took from it some pots ki, tasted the honey from each pot and put all those pots on some shelf vi. As Winnie chose the pots, he followed his intuition. And that means that among all sets of ki pots on shelf ui, he equiprobably chooses one.

Now Winnie remembers all actions he performed with the honey pots. He wants to take to the party the pot he didn't try the day before. For that he must know the mathematical expectation of the number m of shelves that don't have a single untasted pot. To evaluate his chances better, Winnie-the-Pooh wants to know the value m after each action he performs.

Your task is to write a program that will find those values for him.

Input

The first line of the input contains a single number n (1 ≤ n ≤ 105) — the number of shelves at Winnie's place. The second line contains nintegers ai (1 ≤ i ≤ n, 0 ≤ ai ≤ 100) — the number of honey pots on a shelf number i.

The next line contains integer q (1 ≤ q ≤ 105) — the number of actions Winnie did the day before. Then follow q lines, the i-th of them describes an event that follows chronologically; the line contains three integers uivi and ki (1 ≤ ui, vi ≤ n, 1 ≤ ki ≤ 5) — the number of the shelf from which Winnie took pots, the number of the shelf on which Winnie put the pots after he tasted each of them, and the number of the pots Winnie tasted, correspondingly.

Consider the shelves with pots numbered with integers from 1 to n. It is guaranteed that Winnie-the-Pooh Never tried taking more pots from the shelf than it has.

Output

For each Winnie's action print the value of the mathematical expectation m by the moment when this action is performed. The relative or absolute error of each value mustn't exceed 10 - 9.

Examples

input

Copy

3
2 2 3
5
1 2 1
2 1 2
1 2 2
3 1 1
3 2 2

output

Copy

0.000000000000
0.333333333333
1.000000000000
1.000000000000
2.000000000000

题意:

你有n(n<=1e5)个货架,每个货架上有a[i](a[i]<=100)罐蜂蜜,接下来要进行m(m<=1e5)次操作,每次操作格式为

u v x  (x<=5)

表示从第u个货架随机取出x罐蜂蜜进行品尝,品尝完后把这x罐蜂蜜全都放到第v个货架上。(有这么多蜂蜜就是任性)

现在问你,每次操作完后,期望的货架个数,这些货架上所有蜂蜜都被品尝过。

思路:

显然对于每个货架,未被尝过的蜂蜜罐数是单调不增的。

我们考虑用dp[i][j]表示第i个货架上有j罐蜂蜜未品尝过的概率。

对于输入的a[i]显然dp[i][a[i]]=1。初始答案ans为所有dp[i][0]的和(1<=i<=n)

对于每次品尝,我们枚举品尝完后该货架上剩下的未被品尝的蜂蜜罐数,再枚举此次选的x罐中从未被品尝过的罐数,用组合数计算一下概率,更新dp[i][j]的值。(1<=i<=n,0<=j<=a[i])

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=1e5+5;
int n,m,k;
ll C[maxn][107];
ll a[maxn],b[maxn];
double dp[maxn][107],ans,tmp;
int main()
{
    rep(i,0,100000)
    {
        C[i][0]=1;
        rep(j,1,min(105,i))
        C[i][j]=C[i-1][j]+C[i-1][j-1];
    }
    while(scanf("%d",&n)!=EOF)
    {
        ans=0;
        rep(i,1,n) {scanf("%lld",&a[i]);b[i]=a[i];dp[i][a[i]]=1;}
        rep(i,1,n) ans+=dp[i][0];
        scanf("%d",&m);
        while(m--)
        {
            int u,v,x;
            scanf("%d%d%d",&u,&v,&x);
            ans-=dp[u][0];
            ll s=C[b[u]][x];
            rep(i,0,a[u])
            {
                tmp=0;
                rep(k,0,x)
                if(b[u]>=i+k) tmp+=dp[u][i+k]*C[i+k][k]*C[b[u]-i-k][x-k]*1.0/(double)s;
                dp[u][i]=tmp;
            }
            b[u]-=x; b[v]+=x;
            ans+=dp[u][0];
            cout<<fixed<<setprecision(12)<<ans<<endl;
        }
    }
    return 0;
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值