[BJOI2019] 光线
有点奇怪的题目
我们设\(dp_i\)表示经过\(1\)单位的光经过前\(i\)面镜子后变成了多少,也就是前\(i\)面镜子整体的透光率
设\(f_i\)表示倒着(即从第\(i\)面镜子到第\(1\)面镜子)射入\(1\)单位的光,反射出去的光为多少,或者说是这\(i\)面镜子整体的反光率
我们考虑如何求出\(dp_i\)和\(f_i\)
先考虑\(dp_i\)
首先有\(dp_{i-1}\)的光直接过来了,这些光有\(a_i\)直接穿过,为\(dp_{i-1}\times a_i\)
还有\(b_i\)被反射回去,也就是是有\(dp_{i-1}\times b_i\)的光倒着穿过了前\(i\)面镜子,反射回来的光是\(dp_{i-1}\times b_i\times f_{i-1}\),这些光又有\(a_i\)穿过第\(i\)面镜子
如果往下继续写,我们会发现得到这样一个柿子
\[dp_{i}=a_i\sum_{j=0}^{\infty}dp_{i-1}(f_{i-1}b_i)^j
\]
对后面求一下和
\[dp_{i}=\frac{a_i\times dp_{i-1}}{1-f_{i-1}b_i}
\]
再来考虑\(f_i\)
首先有\(1\)的光射了过来,有\(b_i\)直接被反射回去,这里是\(b_i\)
但是有\(a_i\)的光射了进去,所以有\(f_{i-1}\times a_i\)的光被反射回来,这些光在经过第\(i\)面镜子,反射出来的是\(f_{i-1}\times a_i^2\)
继续往下写,我们得到了这样的柿子
\[f_i=b_i+\sum_{j=0}^{\infty}a_i^2f_{i-1}(f_{i-1}b_i)^j=b_i+\frac{f_{i-1}\times a_{i}^2}{1-f_{i-1}b_i}
\]
于是我们递推就好了,答案就是\(dp_n\)
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
const int maxn=5e5+5;
const int inv=570000004;
const int mod=1e9+7;
inline int read() {
char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int n;
int dp[maxn],a[maxn],b[maxn],f[maxn];
inline int ksm(int a,int b) {
int S=1;
while(b) {if(b&1) S=(1ll*S*a)%mod;b>>=1;a=(1ll*a*a)%mod;}
return S;
}
int main() {
n=read();
for(re int i=1;i<=n;i++) a[i]=read(),b[i]=read();
for(re int i=1;i<=n;i++) a[i]=(1ll*a[i]*inv)%mod,b[i]=(1ll*b[i]*inv)%mod;
dp[1]=a[1],f[1]=b[1];
for(re int i=2;i<=n;i++) {
int Inv=ksm(1-1ll*b[i]*f[i-1]%mod+mod,mod-2);
f[i]=(1ll*a[i]*a[i]%mod*f[i-1]%mod*Inv%mod);
f[i]=(f[i]+b[i])%mod;
dp[i]=(1ll*a[i]*dp[i-1]%mod*Inv)%mod;
}
printf("%d\n",dp[n]);
return 0;
}