1. 程式人生 > >BZOJ5091: [Lydsy1711月賽]摘蘋果(簡單概率)

BZOJ5091: [Lydsy1711月賽]摘蘋果(簡單概率)

5091: [Lydsy1711月賽]摘蘋果

Time Limit: 1 Sec  Memory Limit: 256 MB
Submit: 214  Solved: 163
[Submit][Status][Discuss]

Description

小Q的工作是採摘花園裡的蘋果。在花園中有n棵蘋果樹以及m條雙向道路,蘋果樹編號依次為1到n,每條道路的兩 端連線著兩棵不同的蘋果樹。假設第i棵蘋果樹連線著d_i條道路。小Q將會按照以下方式去採摘蘋果: 1.小Q隨機移動到一棵蘋果樹下,移動到第i棵蘋果樹下的概率為d_i/(2m),但不在此採摘。 2.等概率隨機選擇一條與當前蘋果樹相連的一條道路,移動到另一棵蘋果樹下。 3.假設當前位於第i棵蘋果樹下,則他會採摘a_i個蘋果,多次經過同一棵蘋果樹下會重複採摘。 4.重複第2和3步k次。 請寫一個程式幫助計算小Q期望摘到多少蘋果。

Input

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

第二行包含n個正整數,依次表示a_1,a_2,...,a_n(1<=a_i<=100)。 接下來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。

 

思路:一開始選擇每個點的概率為di/2m。 然後轉移的概率,可以猜到也是這個。。。。不會證明。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=100010;
const int Mod=1e9+7;
ll a[maxn],d[maxn],ans;
ll qpow(ll w,ll x){
    ll res
=1; while(x){ if(x&1LL) res=res*w%Mod; w=w*w%Mod; x>>=1; } return res; } int main() { ll N,M,K,u,v; scanf("%lld%lld%lld",&N,&M,&K); rep(i,1,N) scanf("%lld",&a[i]); rep(i,1,M){ scanf("%lld%lld",&u,&v); d[u]++; d[v]++; } rep(i,1,N) ans=(ans+a[i]*d[i])%Mod; ans=(ans*K)%Mod; ans=ans*qpow(2*M,Mod-2)%Mod; printf("%lld\n",ans); return 0; }