【51nod 2015】诺德街

题目

题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=2015
又仁慈、又善良、又有钱的夹克老爷买下了一条街!
懂得经商的夹克老爷决定沿街开 \(n\) 个店铺,从南到北编号为 \(1~n\)。经过紧张的筹备之后,诺德街的 \(n\) 个店铺同时开张了。由于刚开业,夹克老爷的人手不是非常足够,所以需要夹克老爷自己去干活。然而夹克老爷的手下们干活不积极,使得第 \(i\) 个店铺在每分钟都有 \(p_i\) 的概率无人营业,且每分钟之间相互独立。于是夹克老爷从 1 号店铺出发向北走,当遇到第一个无人营业的店铺时就进去营业而停止移动。如果一直走到第 \(n\) 个店铺都有人营业,则原路返回,然后不停地来回走直到遇到一个无人营业的店铺为止。现在夹克老爷想知道,自己期望走多少分钟。假设夹克老爷从一个店铺到下一个店铺需要 1 分钟。
\(n\leq 10^6\)

思路

个人认为,这种存在无限种情况的,存在“循环”的期望题目,多半是要设答案或中间变量为 \(x\),然后分类讨论循环与否的贡献,然后解方程。
发现本题存在循环 \(1\to 2\to ...\to n\to (n-1)\to (n-2)\to ...\to 2\),设一次循环后仍然没有结束的期望为 \(s\),若停止则期望走 \(len\) 步,那么有

\[s=(1-p_1)(1-p_2)...(1-p_n)(1-p_{n-1})...(1-p_2) \]

\[len=\sum^{n}_{i=1}s_i·p_i·(i+1)+\sum^{n-1}_{i=2}s_{2n-i}·p_i·(2n-i-1) \]

可以在 \(O(n)\) 的时间复杂度内求出 \(s\)\(len\)。然后答案 \(ans\) 可能是直接在这一圈停下来 \((len)\),也可能还要走下一圈 \((ans+2n-n)\),其中后者期望为 \(s\)
所以有

\[ans=s·(ans+2n-2)+len \]

解方程即可解出 \(ans\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=2000010,MOD=1e9+7;
ll n,s,len,ans,a,b,c,p[N];

ll fpow(ll x,int k)
{
	ll ans=1;
	for (;k;k>>=1,x=x*x%MOD)
		if (k&1) ans=ans*x%MOD;
	return ans;
}

int main()
{
	scanf("%lld%lld%lld%lld%lld",&n,&p[1],&a,&b,&c);
	for (int i=2;i<=n;i++)
		p[i]=p[n*2-i]=(a*p[i-1]%MOD*p[i-1]+b*p[i-1]+c)%MOD;
	s=1;
	for (int i=1;i<=2*n-2;i++)
	{
		len=(len+s*p[i]%MOD*(i-1))%MOD;
		s=s*(1-p[i])%MOD;
	}
	ans=(2LL*n*s%MOD-2*s+len)%MOD*fpow(1-s,MOD-2)%MOD;
	printf("%lld",(ans%MOD+MOD)%MOD);
	return 0;
}
posted @ 2020-08-11 22:14  stoorz  阅读(129)  评论(0编辑  收藏  举报