题目描述
当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收。
设对于任意 �x,有 �×��%x×ai% 单位的光会穿过它,有 �×��%x×bi% 的会被反射回去。 现在 �n 层玻璃叠在一起,有 11 单位的光打到第 11 层玻璃上,那么有多少单位的光能穿过所有 �n 层玻璃呢?
输入格式
第一行一个正整数 �n,表示玻璃层数。 接下来 �n 行,每行两个非负整数 ��,��ai,bi,表示第 �i 层玻璃的透光率和反射率。
输出格式
输出一行一个整数,表示穿透所有玻璃的光对 109+7109+7 取模的结果。 可以证明,答案一定为有理数。设答案为 �/�a/b ( �a 和 �b 是互质的正整数),你输出的答案为 �x,你需要保证 �≡�� (mod 109+7)a≡bx (mod 109+7)。
样例 #1
样例输入 #1
2
50 20
80 5
Copy
样例输出 #1
858585865
Copy
样例 #2
样例输入 #2
3
1 2
3 4
5 6
Copy
样例输出 #2
843334849
Copy
提示
样例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 单位。在模 109+7109+7 意义下等于 858585865858585865。
数据范围: 对于 5%5% 的数据,�=1n=1; 对于 20%20% 的数据,�≤2n≤2; 对于 30%30% 的数据,�≤3n≤3; 对于 50%50% 的数据,�≤100n≤100; 对于 70%70% 的数据,�≤3000n≤3000; 对于 100%100% 的数据,�≤5×105n≤5×105,1≤��≤1001≤ai≤100,0≤��≤990≤bi≤99,1≤��+��≤1001≤ai+bi≤100。
每组 ��ai 和 ��bi 在满足上述限制的整数中随机生成。
解析::::
说实话,一读题第一反应竟是“bjoi就这?”但是,看完样例的分析我傻了,是我理解错题意了······赶紧从头又分析了一遍,感觉没问题了,便开始敲代码,结果敲了半个小时发现,好像还没有完全理解,再一次回头分析了一下样例(这提醒我们,一定要审好题,理解题意后在动手,要不然就会像我一样,浪费时间),发现第一面和最后一面的反射率是不一样的,我竟然还天真的认为反射率是一样的,不过透光率是一样的(经过计算可知),所以呢,这样就很容易了,只需要维护两个变量即可:
1、光从第 1 面玻璃射入时的透光率。
2、光从第 i 面玻璃射入时的反射率。
��=��−1��∑�=0∞(��−1��)�pi=pi−1ai∑k=0∞(qi−1bi)k
��=��+��−1��2∑�=0∞(��−1��)�qi=bi+qi−1ai2∑k=0∞(qi−1bi)k
其中,还可以进一步优化:带有**∑�=0∞��∑k=0∞ak的形式,当∣�∣∣a∣<1时,它等于11−�1−a1**
所以:
��=��−1��1−��−1��Pi=1−Qi−1biPi−1ai
��=��+��−1��21−��−1��Qi=bi+1−Qi−1biQi−1ai2
可以先计算出**11−��−1��1−Qi−1bi1**简化计算
最后,贴上代码:
#include<bits/stdc++.h>
#define N 1000010
#define int long long
#define INF 0x3f3f3f3f
const int Mod = 1e9 + 7;
const int Inv100 = 570000004;//(pow(100, Mod - 2));
#define ld long double
#define M 1010
#define R register int
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return x*=f;
}
inline void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
int n;
int p, q;//p:前 i 面玻璃按顺序叠在一起后,光从第 1 面玻璃射入时的透光率。
//q:前 i 面玻璃按顺序叠在一起后,光从第 i 面玻璃射入时的反射率。
inline int Inv(int x){
int a = 1;
for (int i = Mod - 2; i; i >>= 1){
if(i&1) a = a * x % Mod;
x = x * x % Mod;
}
return a;
}
signed main(){
n = read();
p = 1, q = 0;
while(n--){
int a = read(), b = read();
a = a * Inv100 % Mod;
b = b * Inv100 % Mod;
int d = Inv(1 - q * b % Mod + Mod) % Mod;
q = (b + a * a % Mod * q % Mod * d) % Mod;
p = p * a % Mod * d % Mod;
}
write(p);
return 0;
}