[BJOI2019]光线

传送门

题目大意

n n n 层玻璃,每一层都有 a % a\% a% 的透光率和 b % b\% b% 的反光率(剩下的会被吸收),现有 1 1 1 单位光打向第一层玻璃,求有多少单位的光透过所有玻璃,对 1 0 9 + 7 10^9+7 109+7 取模。

Solution

不要 nt 了,这题模拟会吐的。看样例的图就知道了。

那很自然会想到线性递推。首先很容易想到设 d p i dp_i dpi 表示 1 1 1 单位光线透过前 i i i 层玻璃后的光线数。则:

d p i = d p i − 1 × a i + s t h . dp_i=dp_{i-1}\times a_i+sth. dpi=dpi1×ai+sth.

发现这个 s t h . sth. sth. 非常鬼畜,于是尝试再设一个东西方便于表示它。

r e s k res_k resk 是穿过前 i − 1 i-1 i1 层后在第 i i i 层反射后从前 i − 1 i-1 i1 层反射回来,并如此 k k k 次后透过第 i i i 层的光线数。则:

r e s k = d p i − 1 × ( b i × s t h . ) k × a i res_k=dp_{i-1}\times (b_i\times sth.)^k\times a_i resk=dpi1×(bi×sth.)k×ai

可以想到,这里的 s t h . sth. sth. 是光线从第 i − 1 i-1 i1 层往回射时再反射回来的光线,不妨设为 r f i − 1 rf_{i-1} rfi1。则:

r e s k = d p i − 1 × ( b i × r f i − 1 ) k × a i res_k=dp_{i-1}\times (b_i\times rf_{i-1})^k\times a_i resk=dpi1×(bi×rfi1)k×ai

然后可以得出 d p dp dp 的递推式:

d p i = ∑ k = 0 + ∞ r e s k = ∑ k = 0 + ∞ ( d p i − 1 × ( b i × r f i − 1 ) k × a i ) = d p i − 1 × a i × ∑ k = 0 + ∞ ( b i × r f i − 1 ) k dp_i=\sum_{k=0}^{+\infty}res_k=\sum_{k=0}^{+\infty}(dp_{i-1}\times (b_i\times rf_{i-1})^k\times a_i)=dp_{i-1}\times a_i\times\sum_{k=0}^{+\infty} (b_i\times rf_{i-1})^k dpi=k=0+resk=k=0+(dpi1×(bi×rfi1)k×ai)=dpi1×ai×k=0+(bi×rfi1)k

好我们假装这个东西可以线性递推了……个鬼啊。

好的我们发现这玩意儿有个无限等比数列,好我们把它求出来:

S = 1 + ( b i × r f i − 1 ) + ( b i × r f i − 1 ) 2 + ( b i × r f i − 1 ) 3 + ⋯ S=1+(b_i\times rf_{i-1})+(b_i\times rf_{i-1})^2+(b_i\times rf_{i-1})^3+\cdots S=1+(bi×rfi1)+(bi×rfi1)2+(bi×rfi1)3+

所以有:

( b i × r f i − 1 ) × S = ( b i × r f i − 1 ) + ( b i × r f i − 1 ) 2 + ( b i × r f i − 1 ) 3 + ⋯ (b_i\times rf_{i-1})\times S=(b_i\times rf_{i-1})+(b_i\times rf_{i-1})^2+(b_i\times rf_{i-1})^3+\cdots (bi×rfi1)×S=(bi×rfi1)+(bi×rfi1)2+(bi×rfi1)3+

所以有:

S − ( b i × r f i − 1 ) × S = 1 S-(b_i\times rf_{i-1})\times S=1 S(bi×rfi1)×S=1

好直接把 S S S 解出来, S = 1 1 − ( b i × r f i − 1 ) S=\dfrac{1}{1-(b_i\times rf_{i-1})} S=1(bi×rfi1)1

好了我们发现这就好了……个鬼啊!

r f rf rf 怎么求呢?

好问题。

好的其实很简单。

r f i = b i + a i × ∑ k = 0 + ∞ ( b i × r f i − 1 ) k × a i rf_i=b_i+a_i\times \sum_{k=0}^{+\infty} (b_i\times rf_{i-1})^k\times a_i rfi=bi+ai×k=0+(bi×rfi1)k×ai

对吧,就是要么直接被 i i i 直接反射,要么透过去后又是那个反复横跳 k ( k ≥ 0 ) k(k\ge0) k(k0) 次后透过 i i i 的光加起来就是力!

所以直接把 S S S 带进去就好力!

综上,有:
d p i = d p i − 1 × a i 1 − ( b i × r f i − 1 ) dp_i=\dfrac{dp_{i-1}\times a_i}{1-(b_i\times rf_{i-1})} dpi=1(bi×rfi1)dpi1×ai

r f i = b i + a i 2 1 − ( b i × r f i − 1 ) rf_i=b_i+\dfrac{a_i^2}{1-(b_i\times rf_{i-1})} rfi=bi+1(bi×rfi1)ai2

注意细节。

Code

#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
using namespace std;
const int MAXN=5e5+10;
const ll MOD=1e9+7;
ll ksm(ll a,ll p){
	ll ret=1;
	while(p){
		if(p&1) ret=ret*a%MOD;
		a=a*a%MOD; p>>=1;
	}return ret;
}
ll inv(ll x){return ksm(x,MOD-2);}//哦逆元搞心态
ll a[MAXN],b[MAXN],dp[MAXN],rf[MAXN];
int main()
{
	int n;
	scanf("%d",&n);
	ll inv100=inv(100);
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&a[i],&b[i]);
		a[i]=a[i]*inv100%MOD;
		b[i]=b[i]*inv100%MOD;
	}
	dp[1]=a[1];rf[1]=b[1];
	for(int i=2;i<=n;i++){
		rf[i]=(b[i]+a[i]*a[i]%MOD*rf[i-1]%MOD*inv(((1-b[i]*rf[i-1]%MOD)%MOD+MOD)%MOD)%MOD)%MOD;
		dp[i]=(dp[i-1]*a[i]%MOD*inv(((1-b[i]*rf[i-1]%MOD)%MOD+MOD)%MOD)%MOD)%MOD;//减法搞心态
	}
	printf("%lld\n",dp[n]);
}

End

好的校内模拟赛 T1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值