题目vj链接

题面:

题意:
n n n 个物品,取走第 i i i 个物品有 1 2 \frac{1}{2} 21 的概率花费 t i ti ti 的时间,有 1 2 \frac{1}{2} 21的概率花费 t i + 1 ti+1 ti+1 的时间,必须按照 1 n 1-n 1n的顺序取走物品。

给定时间和 T T T,问在 T T T 内能取走物品的个数的期望。

题解:
我们设 s u m [ i ] t [ i ] sum[i]为t[i]的前缀和 sum[i]t[i],我们找到最大的 p o s pos pos 满足 s u m [ p o s ] < = T sum[pos]<=T sum[pos]<=T

然后我们枚举前 p o s pos pos 个物品有几个物品花费了 t i + 1 ti+1 ti+1 的时间。

(1)假设有 x x x 个物品花费了 t i + 1 ti+1 ti+1 的时间,且满足 x + s u m [ p o s ] < = T x+sum[pos]<=T x+sum[pos]<=T,那么期望 a n s + = ( 1 2 ) p o s C ( p o s , x ) p o s ans+=(\frac{1}{2})^{pos}*C(pos,x)*pos ans+=(21)posC(pos,x)pos

(2)假设有 x x x 个物品花费了 t i + 1 ti+1 ti+1 的时间,且满足 x + s u m [ p o s ] = T + 1 x+sum[pos]=T+1 x+sum[pos]=T+1,那么只能取走 p o s 1 pos-1 pos1 个物品:
若这 x x x 个物品中有第 p o s pos pos 个,即第 p o s pos pos 个物品的状态已经确定,此时 a n s + = ( 1 2 ) ( 1 2 ) p o s 1 C ( p o s 1 , x 1 ) ( p o s 1 ) ans+=(\frac{1}{2})*(\frac{1}{2})^{pos-1}*C(pos-1,x-1)*(pos-1) ans+=(21)(21)pos1C(pos1,x1)(pos1)
若这 x x x 个物品中没有第 p o s pos pos 个,那么第 p o s pos pos 个物品的状态无论是否 + 1 +1 +1,都不会取到第 p o s pos pos 个,即此时第 p o s pos pos 个的状态没有影响。此时 a n s + = ( 1 2 ) p o s 1 C ( p o s 1 , x ) ( p o s 1 ) ans+=(\frac{1}{2})^{pos-1}*C(pos-1,x)*(pos-1) ans+=(21)pos1C(pos1,x)(pos1)

若再去枚举有 x + 1 x+1 x+1 个物品花费了 t i + 1 ti+1 ti+1 的时间的时候, x + s u m [ p o s ] = T + 2 x+sum[pos]=T+2 x+sum[pos]=T+2,此时第 p o s pos pos个物品一定不会取到,所以状态没有影响,直接不考虑第 p o s pos pos 个即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=200100;
const int maxm=100100;
const int maxp=100100;
const int up=100100;


ll n,tt;
ll t[maxn],sum[maxn];
ll fac[maxn],inv[maxn];

ll mypow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

void init(int n)
{
    for(int i=1;i<=n;i++)
        scanf("%lld",&t[i]),sum[i]=sum[i-1]+t[i];
    fac[0]=1;
    for(int i=1;i<=n;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[n]=mypow(fac[n],mod-2);
    for(int i=n-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}

ll C(int n,int m)
{
    if(n<0||m<0||m>n) return 0;
    return fac[n]*inv[m]%mod*inv[n-m]%mod;
}

int main(void)
{
    scanf("%lld%lld",&n,&tt);
    ll inv2=mypow(2,mod-2);
    init(n);

    int pos=n;
    for(int i=1;i<=n;i++)
    {
        if(sum[i]>tt)
        {
            pos=i-1;
            break;
        }
    }
    ll nowt=sum[pos];
    ll ans=0;
    for(int x=0;x<=pos;x++)
    {
        if(nowt+x<=tt)
        {
            ans=(ans+mypow(inv2,pos)*C(pos,x)%mod*pos%mod)%mod;
        }
        else
        {
            ans=(ans+inv2*mypow(inv2,pos-1)%mod*C(pos-1,x-1)%mod*(pos-1)%mod)%mod;
            ans=(ans+mypow(inv2,pos-1)*C(pos-1,x)%mod*(pos-1)%mod)%mod;
            nowt-=t[pos--];
        }
    }
    printf("%lld\n",ans);
    return 0;
}