牛客网暑期ACM多校训练营(第九场)E:Music Game(单位求贡献)

 

题目大意:

有n个点,每个点被点击的成功率为p[i]/100,如果有连续的x点成功被点击,你将获得x^m次方的分数,问你在已知所有点被点击成功的概率的情况下,问你最后获得分数的期望。

 

解题思路:

思路的话其实我感觉对于期望题我就只会对单位求贡献,这个题目也是一样的。就是从这个位置开始连续x点成功的概率*获得分数,算起来也很简单,假设从 i 开始 连续 x 个成功的概率 ,其实就是 i-1 失败的概率 * i开始连续x个成功的概率*之后一个点失败的概率。这样的话算法的复杂度是 n^2,与m就没有关系了,但是出题人说有另一种n*m的解法,目前还不是很懂,以后学习一下。

 

Ac代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
int n,m;
ll a[maxn],b[maxn],inv[maxn],val[maxn];
int main()
{
    scanf("%d%d",&n,&m);
    b[0]=1; b[n+1]=1; val[0]=1; inv[0]=1;   //注意inv[0]=1 被坑了好久
    ll gk=powmod(100,mod-2);    //对100先预处理逆元
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        b[i]=b[i-1]*a[i]%mod*gk%mod;    //求出连续成功的前缀和
        if(b[i]==0) inv[i]=1,b[i]=1;    //这里注意要特殊处理
        else inv[i]=powmod(b[i],mod-2);
        val[i]=powmod(i,m);
    }
    ll res=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0) continue;   //这里注意也要处理一下
        for(int j=i;j<=n;j++)
        {
            if(a[j]==0) break;  //同上
            res=(res+(100-a[i-1])%mod*gk%mod*b[j]%mod*inv[i-1]%mod*(100-a[j+1])%mod*gk%mod*val[j-i+1]%mod)%mod; //加上它对答案的贡献
        }
    }
    res=(res+mod)%mod;
    printf("%lld\n",res);
    //system("pause");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值