您的位置:首页 > 其它

bzoj 5091 摘苹果

2018-03-23 22:10 176 查看
BZOJ 5091

一道毫无编程难度的题,再不写点啥就说不过去了。。。

在雅礼集训上听tzt大佬讲了一波,感觉应该还挺好写?于是手算想通之后果断水了一波;

首先设个状态,f[j][i]表示当前走了j步到i节点的概率,f[0][i]显然就是第一步到j节点的概率,等于di/2*m;

那么答案就是∑k=1K∑i=1nf[k][i]∗ai∑k=1K∑i=1nf[k][i]∗ai

首先手玩一下f[1][i]的答案;

对与i点向外连向的每一个点,其概率为f[0][i]/di,也就是1/2m,也就是说每个点的每个入度给其带来了1/2m的概率,由于是无向图,很容易就能得出f[1][i]=di/2m,继续向下推也一样,f[j][i]始终等于di/2m;

那么答案就变成了∑i=1nK∗di∗ai2∗m∑i=1nK∗di∗ai2∗m

求个逆元乘一下就好了(我才不会说我忘取模wa了一发

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
const int maxn=100005;
int n,m,k;
int a[maxn];
int d[maxn];
const int mod=1e9+7;
void exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return;
}
exgcd(b,a%b,x,y);
int tp=x;
x=y;
y=tp-(a/b)*y;
return;
}
int inv(int v){
int x,y;
exgcd(v,mod,x,y);
return (x+mod)%mod;
}
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 tp1,tp2;
scanf("%d%d",&tp1,&tp2);
d[tp1]++,d[tp2]++;
}
int ans=0;
int re=inv(2*m);
for(int i=1;i<=n;i++){
ans+=((LL)a[i]*(LL)d[i]%mod)*((LL)k*(LL)re%mod)%mod;
ans%=mod;
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: