bzoj 5091 摘苹果

BZOJ 5091
一道毫无编程难度的题,再不写点啥就说不过去了。。。
在雅礼集训上听大佬讲了一波,感觉应该还挺好写?于是手算想通之后果断水了一波;
首先设个状态,f[j][i]表示当前走了j步到i节点的概率,f[0][i]显然就是第一步到j节点的概率,等于di/2*m;
那么答案就是

k=1Ki=1nf[k][i]ai ∑ k = 1 K ∑ i = 1 n f [ k ] [ i ] ∗ a i

首先手玩一下f[1][i]的答案;
对与i点向外连向的每一个点,其概率为f[0][i]/di,也就是1/2m,也就是说每个点的每个入度给其带来了1/2m的概率,由于是无向图,很容易就能得出f[1][i]=di/2m,继续向下推也一样,f[j][i]始终等于di/2m;
那么答案就变成了
i=1nKdiai2m ∑ i = 1 n K ∗ d i ∗ a i 2 ∗ 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值