题目大意
有 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=dpi−1×ai+sth.
发现这个 s t h . sth. sth. 非常鬼畜,于是尝试再设一个东西方便于表示它。
设 r e s k res_k resk 是穿过前 i − 1 i-1 i−1 层后在第 i i i 层反射后从前 i − 1 i-1 i−1 层反射回来,并如此 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=dpi−1×(bi×sth.)k×ai
可以想到,这里的 s t h . sth. sth. 是光线从第 i − 1 i-1 i−1 层往回射时再反射回来的光线,不妨设为 r f i − 1 rf_{i-1} rfi−1。则:
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=dpi−1×(bi×rfi−1)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∑+∞(dpi−1×(bi×rfi−1)k×ai)=dpi−1×ai×k=0∑+∞(bi×rfi−1)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×rfi−1)+(bi×rfi−1)2+(bi×rfi−1)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×rfi−1)×S=(bi×rfi−1)+(bi×rfi−1)2+(bi×rfi−1)3+⋯
所以有:
S − ( b i × r f i − 1 ) × S = 1 S-(b_i\times rf_{i-1})\times S=1 S−(bi×rfi−1)×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×rfi−1)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×rfi−1)k×ai
对吧,就是要么直接被 i i i 直接反射,要么透过去后又是那个反复横跳 k ( k ≥ 0 ) k(k\ge0) k(k≥0) 次后透过 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×rfi−1)dpi−1×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×rfi−1)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。