【DP】[BJOI2019]光线

题目

题目描述
当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收。

设对于任意 xx,有 x \times a_i%x×a
i

% 单位的光会穿过它,有 x \times b_i%x×b
i

% 的会被反射回去。
现在 nn 层玻璃叠在一起,有 11 单位的光打到第 11 层玻璃上,那么有多少单位的光能穿过所有 nn 层玻璃呢?

输入格式
第一行一个正整数 nn,表示玻璃层数。
接下来 nn 行,每行两个非负整数 a_i,b_ia
i

,b
i

,表示第 ii 层玻璃的透光率和反射率。

输出格式
输出一行一个整数,表示穿透所有玻璃的光对 10^9 + 710
9
+7 取模的结果。
可以证明,答案一定为有理数。设答案为 a/ba/b ( aa 和 bb 是互质的正整数),你输出的答案为 xx,你需要保证 a\equiv bx \space (\text{mod }10^9 + 7)a≡bx (mod 10
9
+7)。

输入输出样例
输入 #1复制
2
50 20
80 5
输出 #1复制
858585865
输入 #2复制
3
1 2
3 4
5 6
输出 #2复制
843334849
说明/提示
样例1解释:

如图,光线从左上角打进来,有 0.50.5 单位的光穿过第 11 层玻璃,有 0.20.2 单位的光被反射回去。这 0.50.5 单位的光有 0.40.4 单位穿过第 22 层玻璃,有 0.0250.025 单位的光被反射回去。这 0.0250.025 单位的光有 0.01250.0125 单位穿过第 11 层玻璃,有 0.0050.005 单位的光被反射回去。这 0.0050.005 单位的光有 0.0040.004 单位穿过第 22 层玻璃……于是,穿过两层玻璃的光一共有0.40404… = 40/990.40404…=40/99 单位。在模 10^9+710
9
+7 意义下等于 858585865858585865。

数据范围:
对于 5%5% 的数据,n=1n=1;
对于 20%20% 的数据,n\le 2n≤2;
对于 30%30% 的数据,n\le 3n≤3;
对于 50%50% 的数据,n\le 100n≤100;
对于 70%70% 的数据,n\le 3000n≤3000;
对于 100%100% 的数据,n\le 5\times 10^5n≤5×10
5
,1\le a_i \le 1001≤a
i

≤100,0\le b_i \le 990≤b
i

≤99,1\le a_i+b_i \le 1001≤a
i

+b
i

≤100。

每组 a_ia
i

和 b_ib
i

在满足上述限制的整数中随机生成。

思路

我们设 d p i dp_i dpi表示经过 1 1 1单位的光经过前 i i i面镜子后变成了多少,也就是前 i i i面镜子整体的透光率
f i f_i fi表示倒着(即从第 i i i面镜子到第 1 1 1面镜子)射入 1 1 1单位的光,反射出去的光为多少,或者说是这 i i i面镜子整体的反光率
我们考虑如何求出 d p i dp_i dpi f i f_i fi
先考虑 d p i dp_i dpi
首先有 d p i − 1 dp_{i-1} dpi1的光直接过来了,这些光有 a i a_i ai直接穿过,为 d p i − 1 × a i dp_{i-1}\times a_i dpi1×ai
还有 b i b_i bi被反射回去,也就是是有 d p i − 1 × b i dp_{i-1}\times b_i dpi1×bi的光倒着穿过了前 i i i面镜子,反射回来的光是 d p i − 1 × b i × f i − 1 dp_{i-1}\times b_i\times f_{i-1} dpi1×bi×fi1,这些光又有 a i a_i ai穿过第 i i i面镜子
如果往下继续写,我们会发现得到这样一个柿子
d p i = a i ∑ j = 0 ∞ d p i − 1 ( f i − 1 b i ) j dp_{i}=a_i\sum_{j=0}^{\infty}dp_{i-1}(f_{i-1}b_i)^j dpi=aij=0dpi1(fi1bi)j
对后面求一下和
d p i = a i × d p i − 1 1 − f i − 1 b i dp_{i}=\frac{a_i\times dp_{i-1}}{1-f_{i-1}b_i} dpi=1fi1biai×dpi1
再来考虑 f i f_i fi
首先有 1 1 1的光射了过来,有 b i b_i bi直接被反射回去,这里是 b i b_i bi
但是有 a i a_i ai的光射了进去,所以有 f i − 1 × a i f_{i-1}\times a_i fi1×ai的光被反射回来,这些光在经过第 i i i面镜子,反射出来的是 f i − 1 × a i 2 f_{i-1}\times a_i^2 fi1×ai2
继续往下写,我们得到了这样的柿子
f i = b i + ∑ j = 0 ∞ a i 2 f i − 1 ( f i − 1 b i ) j = b i + f i − 1 × a i 2 1 − f i − 1 b i 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} fi=bi+j=0ai2fi1(fi1bi)j=bi+1fi1bifi1×ai2
于是我们递推就好了,答案就是 d p n dp_n dpn

代码

#include<bits/stdc++.h>
#define MAXN 500005
#define reg register
#define inl inline
#define int long long
using namespace std;
const int Mod=1e9+7;
int n,a[MAXN],b[MAXN],f[MAXN],g[MAXN];
inl int Add(reg int x,reg int y)
{
    return x+y>Mod?x+y-Mod:x+y;
}
inl int Dec(reg int x,reg int y)
{
    return x-y<0?x-y+Mod:x-y;
}
inl int Mul(reg int x,reg int y)
{
    return x*y-x*y/Mod*Mod;
}
inl int Pow(reg int x,reg int y)
{
    reg int res=1;
    for(;y;y>>=1,x=Mul(x,x)) if(y&1) res=Mul(res,x);
    return res;
}
signed main()
{
    reg int inv=Pow(100,Mod-2);
    scanf("%lld",&n);
    for(reg int i=1;i<=n;i++)
    {
        scanf("%lld %lld",&a[i],&b[i]);
        a[i]=Mul(inv,a[i]);
        b[i]=Mul(inv,b[i]);
    }
    f[0]=1;
    for(reg int i=1;i<=n;i++)
    {
        reg int p=Pow(Dec(1,Mul(g[i-1],b[i])),Mod-2);
        f[i]=Mul(Mul(f[i-1],a[i]),p);
        g[i]=Add(b[i],Mul(Mul(Mul(g[i-1],a[i]),a[i]),p));
    }
    printf("%lld\n",f[n]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值