有点奇怪的题目
我们设(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} imes a_i)
还有(b_i)被反射回去,也就是是有(dp_{i-1} imes b_i)的光倒着穿过了前(i)面镜子,反射回来的光是(dp_{i-1} imes b_i imes f_{i-1}),这些光又有(a_i)穿过第(i)面镜子
如果往下继续写,我们会发现得到这样一个柿子
[dp_{i}=a_isum_{j=0}^{infty}dp_{i-1}(f_{i-1}b_i)^j
]
对后面求一下和
[dp_{i}=frac{a_i imes dp_{i-1}}{1-f_{i-1}b_i}
]
再来考虑(f_i)
首先有(1)的光射了过来,有(b_i)直接被反射回去,这里是(b_i)
但是有(a_i)的光射了进去,所以有(f_{i-1} imes a_i)的光被反射回来,这些光在经过第(i)面镜子,反射出来的是(f_{i-1} imes 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} imes 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
",dp[n]);
return 0;
}