1. 程式人生 > >bzoj 5091: [Lydsy0711月賽]摘蘋果

bzoj 5091: [Lydsy0711月賽]摘蘋果

bmi gpo c++ scanf 依次 can log 就是 幫助

5091: [Lydsy0711月賽]摘蘋果

Time Limit: 1 Sec Memory Limit: 256 MB
Submit: 148 Solved: 114
[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。
讓我們設f[i][j]為走了i次之後到j的概率。 顯然 f[0][j] = d[j]/2m 。 然後答案就是ΣΣf[i][j] * a[j] 但其實不管i是多少,f[i][j] 都等於 d[j]/2m ,接下來我來證明這一點。 因為f[0][j] 等於 d[j]/2m ,所以我們第一次走上每條邊(考慮方向的話是有2m條邊的)的概率都是1/2m, 所以每個點被走到的概率就是d[j]/2m,也就是f[1][j] = f[0][j] 。 然後就證出來了2333
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=200005;
const int ha=1000000007;
int inv,n,m,ans;
int k,d[maxn],a[maxn];

inline int add(int x,int y){
	x+=y;
	return x>=ha?x-ha:x;
}

inline int ksm(int x,int y){
	int an=1;
	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
	return an;
}

int main(){
    scanf("%d%d%d",&n,&m,&k);
    int uu,vv; 
	inv=ksm(2*m,ha-2);
	for(int i=1;i<=n;i++) scanf("%d",a+i);
    for(int i=1;i<=m;i++){
    	scanf("%d%d",&uu,&vv);
    	d[uu]++,d[vv]++;
    }
    for(int i=1;i<=n;i++) ans=add(ans,a[i]*d[i]*(ll)inv%ha);
    ans=ans*(ll)k%ha;
    printf("%d\n",ans);
    return 0;
}

  

bzoj 5091: [Lydsy0711月賽]摘蘋果