[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;
}

猜你喜欢

转载自www.cnblogs.com/asuldb/p/10751131.html