「EZEC-6」跳一跳 题解

蓝题都做不出来,我真的是菜到一定境界了。

Description

传送门

Solution

首先,我们先将 a , b a,b a,b 分别变为 a 100 \frac {a} {100} 100a b 100 \frac b {100} 100b 在模 1 0 9 + 7 10^9+7 109+7 意义下的值,并令 x = a + b x=a+b x=a+b

可以发现,答案来源于下面这三个部分的贡献:

①跳到了第 i i i 个位置但没有跳到中心,有 1 1 1 的贡献;
②跳到了第 i i i 个位置且跳到了中心,也有一定的贡献;
③跳到了第 i i i 个关键点 x i x_i xi 的中心,有 y i y_i yi 的贡献。

Part 1

先考虑 ①。

我们枚举 i i i,并求出此事件发生的概率。不难发现,这个概率就是,前 i − 1 i-1 i1 次都不能跳到地上,且第 i i i 次一定要跳到中心旁边的概率,即 x i − 1 b x^{i-1} b xi1b

∑ i = 1 n x i − 1 a = a ∑ i = 0 n − 1 x i = a x n − x 0 x − 1 \begin{aligned} \sum_{i=1}^n x^{i-1} a &= a \sum_{i=0}^{n-1} x^i \\ &= a\frac {x^{n}-x^0} {x-1} \end{aligned} i=1nxi1a=ai=0n1xi=ax1xnx0

采用快速幂+逆元计算即可。

哎,等等,如果 x ≡ 1 ( m o d 1 0 9 + 7 ) x \equiv 1 \pmod {10^9+7} x1(mod109+7) 怎么办?这时分母为 0 0 0,还算个锤子 ⋯ ⋯ \cdots \cdots

考虑将 x ≡ 1 x \equiv 1 x1 带入原式子,有

∑ i = 1 n 1 i − 1 a = a n \sum_{i=1}^n 1^{i-1}a=an i=1n1i1a=an

特判一下这个情况就好了。

真的好了吗?如果 x ≡ 0 x \equiv 0 x0,那么 x 0 x^0 x0 是多少?

于是还要特判 x = 0 x=0 x=0 的情况,此时原式等于 0 0 0

Part 2

枚举关键点 x i x_i xi,并计算出其产生 y i y_i yi 贡献的概率。

不难发现,这个概率就是,成功跳到 x i − 1 x_i-1 xi1 且跳到 x i x_i xi 的中心的概率,即 x x i − 1 b x^{x_i-1} b xxi1b

∑ i = 1 m x x i − 1 b \sum_{i=1}^m x^{x_i-1} b i=1mxxi1b

枚举+快速幂计算即可,复杂度 O ( m log ⁡ n ) O(m \log n) O(mlogn)

Part 3

f i f_i fi 表示,跳到第 i i i 个位置的期望 c n t cnt cnt,则这一部分的贡献是

∑ i = 1 n f i − 1 b = b ( ∑ i = 0 n − 1 f i ) \sum_{i=1}^n f_{i-1} b=b\left(\sum_{i=0}^{n-1} f_i\right) i=1nfi1b=b(i=0n1fi)

考虑通过递推计算出各个 f f f

对于 f i f_i fi 而言,其有两种选择,一是继承 i − 1 i-1 i1 c n t cnt cnt,一是跳到中心旁边将 c n t cnt cnt 更新为 2 2 2。对于前者,其发生的概率为 b b b,贡献为 2 f i − 1 2 f_{i-1} 2fi1;对于后者,其发生的概率为 a × x i − 1 a \times x^{i-1} a×xi1,贡献为 2 2 2。因此有

f i = 2 b f i − 1 + 2 a x i − 1 f_i=2bf_{i-1}+2ax^{i-1} fi=2bfi1+2axi1

g i = ∑ j = 1 i − 1 f i h i = x i g_i=\sum_{j=1}^{i-1} f_i \\ h_i=x^{i} gi=j=1i1fihi=xi

f i = ( 2 b ) f i − 1 + ( 2 a ) h i − 1 f_i=(2b)f_{i-1}+(2a)h_{i-1} fi=(2b)fi1+(2a)hi1 g i = g i − 1 + f i − 1 g_i=g_{i-1}+f_{i-1} gi=gi1+fi1 h i = x h i − 1 h_i=xh_{i-1} hi=xhi1

写成矩阵乘法的形式

[ f i − 1   g i − 1   h i − 1 ] × [ 2 b   1   0 0   1   0 2 a   0   x ] = [ f i   g i   h i ] \begin{bmatrix} f_{i-1} \ g_{i-1} \ h_{i-1}\end{bmatrix} \times \begin{bmatrix}2b \ 1 \ 0 \\ 0 \ 1 \ 0 \\ 2a \ 0 \ x\end{bmatrix}=\begin{bmatrix} f_i \ g_i \ h_i\end{bmatrix} [fi1 gi1 hi1]×2b 1 00 1 02a 0 x=[fi gi hi]

更进一步的

[ 2   0   1 ] × ( [ 2 b   1   0 0   1   0 2 a   0   x ] ) n + 1 = [ f n   g n + 1   h n + 1 ] \begin{bmatrix} 2 \ 0 \ 1\end{bmatrix} \times \left(\begin{bmatrix}2b \ 1 \ 0 \\ 0 \ 1 \ 0 \\ 2a \ 0 \ x\end{bmatrix}\right)^{n+1}=\begin{bmatrix} f_{n} \ g_{n+1} \ h_{n+1}\end{bmatrix} [2 0 1]×2b 1 00 1 02a 0 xn+1=[fn gn+1 hn+1]

其中 g n g_{n} gn 即为这一部分对答案的贡献。


总复杂度 O ( 3 3 log ⁡ n + m log ⁡ n + log ⁡ mod ) O(3^3 \log n+m \log n+\log \text{mod}) O(33logn+mlogn+logmod),本题被解决。

Code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7,maxl=100005;

int read(){
	int s=0,w=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-')  w=-w;ch=getchar();}
	while (ch>='0'&&ch<='9'){s=s*10+(ch^'0');ch=getchar();}
	return s*w;
}
int n,a,b,m,res1,res2,res3,ans;
int x[maxl],y[maxl];

struct Matrix{
	int ma[3][3];
}base;

Matrix operator * (const Matrix x,const Matrix y){
	Matrix z;
	for (int i=0;i<3;i++){
		for (int j=0;j<3;j++){
			z.ma[i][j]=0;
			for (int k=0;k<3;k++)
			  z.ma[i][j]=(z.ma[i][j]+x.ma[i][k]*y.ma[k][j])%mod;
		}
	}
	return z;
}

Matrix matrix_quick_power(Matrix x,int y){
	Matrix res=x;y--;
	for (;y;y=y>>1,x=x*x){
		if (y&1)  res=res*x;
	}
	return res;
}

int quick_power(int x,int y){
	int res=1;
	for (;y;y=y>>1,x=(x*x)%mod){
		if (y&1)  res=(res*x)%mod;
	}
	return res;
}
int ny(int tmpx){return quick_power(tmpx,mod-2);}

void calc1(){
	int val=(a+b)%mod;
	if (val>1)
	  res1=((quick_power(val,n)-1)*ny(val-1))%mod;
	else if (val==1)  res1=n%mod;
	else res1=0;
	
	res1=(res1*a)%mod;
}

void init3(){
	base.ma[0][0]=(2*b)%mod;
	base.ma[0][1]=1;
	base.ma[0][2]=0;
	base.ma[1][1]=1;
	base.ma[2][0]=(2*a)%mod;
	base.ma[2][2]=(a+b)%mod;
}

void calc3(){
	Matrix tmp=matrix_quick_power(base,n);
	int tmp_01=tmp.ma[0][1],tmp_02=tmp.ma[2][1];
	res3=(tmp_01*2+tmp_02)%mod;
	res3=(res3*b)%mod;
}

signed main(){
	n=read(),a=read(),b=read(),m=read();
	a=(a*ny(100))%mod;b=(b*ny(100))%mod;
	for (int i=1;i<=m;i++){
		x[i]=read(),y[i]=read();
		res2=(res2+quick_power(a+b,x[i]-1)*b%mod*y[i])%mod;
	}
	calc1(),init3(),calc3();
	ans=(res1+res2+res3)%mod;
	cout<<ans<<endl;
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值