BZOJ5091: [Lydsy1711月賽]摘蘋果【指望DP】

Description

小Q的工做是採摘花園裏的蘋果。在花園中有n棵蘋果樹以及m條雙向道路,蘋果樹編號依次爲1到n,每條道路的兩c++

端鏈接着兩棵不一樣的蘋果樹。假設第i棵蘋果樹鏈接着d_i條道路。小Q將會按照如下方式去採摘蘋果:spa

1.小Q隨機移動到一棵蘋果樹下,移動到第i棵蘋果樹下的機率爲d_i/(2m),但不在此採摘。code

2.等機率隨機選擇一條與當前蘋果樹相連的一條道路,移動到另外一棵蘋果樹下ip

3.假設當前位於第i棵蘋果樹下,則他會採摘a_i個蘋果,屢次通過同一棵蘋果樹下會重複採摘。input

4.重複第2和3步k次。it

請寫一個程序幫助計算小Q指望摘到多少蘋果。io

Input

第一行包含三個正整數n,m,k(n,k<=100000,m<=200000),分別表示蘋果樹和道路的數量以及重複步驟的次數。ast

第二行包含n個正整數,依次表示a_1,a_2,...,a_n(1<=a_i<=100)。class

接下來m行,每行兩個正整數u,v(1<=u,v<=n,u!=v),表示第u和第v棵蘋果樹之間存在一條道路。程序

Output

若答案爲P/Q,則輸出一行一個整數,即P*Q^{-1} mod 1000000007(10^9+7)。

Sample Input

3 4 2
2 3 4
1 2
1 2
2 3
3 1

Sample Output

750000011
//指望爲5.75=23/4=(23*250000002) mod 1000000007=750000011。


思路

拆開看每一個節點的貢獻

\(f_{i,j}\)表示在第j步走到i點的機率

\(f_{i,0}=\frac{d_i}{2m}\)

那麼\(f_{i,1}=\sum_{i,j\in E}\frac{f_{j,0}}{d_j}=\frac{d_i}{2m}\)

因此獲得\(f_{i,j\in[0,k]}=\frac{d_i}{2m}\)

而後又由於每一個樹的貢獻是\(a_i*\sum_{i=1}^kf_{i,k}=\frac{a_i*d_i*k}{2m}\)

而後就直接算就好了


#include<bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;
const int Mod = 1e9 + 7;

int add(int a, int b) {
  return (a += b) >= Mod ? a - Mod : a;
}

int mul(int a, int b) {
  return 1ll * a * b % Mod;
}

int fast_pow(int a, int b) {
  int res = 1;
  while (b) {
    if (b & 1) res = mul(res, a);
    b >>= 1;
    a = mul(a, a); 
  }
  return res;
}

int n, m, k, d[N], a[N];

int main() {
  scanf("%d %d %d", &n, &m, &k);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
  }
  for (int i = 1; i <= m; i++) {
    int u, v; scanf("%d %d", &u, &v);
    d[u]++;
    d[v]++;
  }
  int cur = 0;
  for (int i = 1; i <= n; i++) {
    cur = add(cur, mul(a[i], d[i]));
  }
  printf("%d", mul(cur, mul(k, fast_pow(m * 2, Mod - 2))));
  return 0;
}
相關文章
相關標籤/搜索