P5323[BJOI2019]光线

//时隔一年,终于又写博客了!(大概是最后一篇博客了吧)之所以写这篇博客呢,是用来纪念我AC600祭(我肯定不会说我是闲得无聊来打发时间的),废话不多说,直接进入正题:


[BJOI2019]光线

题目描述

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

设对于任意 \(x\),有 \(x \times a_i\%\) 单位的光会穿过它,有 \(x \times b_i\%\) 的会被反射回去。

现在 \(n\) 层玻璃叠在一起,有 \(1\) 单位的光打到第 \(1\) 层玻璃上,那么有多少单位的光能穿过所有 \(n\) 层玻璃呢?

输入格式

第一行一个正整数 \(n\),表示玻璃层数。

接下来 \(n\) 行,每行两个非负整数 \(a_i,b_i\),表示第 \(i\) 层玻璃的透光率和反射率。

输出格式

输出一行一个整数,表示穿透所有玻璃的光对 \(10^9 + 7\) 取模的结果。

可以证明,答案一定为有理数。设答案为 \(a/b\) ( \(a\)\(b\) 是互质的正整数),你输出的答案为 \(x\),你需要保证 \(a\equiv bx \space (\text{mod }10^9 + 7)\)

样例 #1

样例输入 #1

2
50 20
80 5

样例输出 #1

858585865

样例 #2

样例输入 #2

3
1 2
3 4
5 6

样例输出 #2

843334849

提示

样例1解释:

如图,光线从左上角打进来,有 \(0.5\) 单位的光穿过第 \(1\) 层玻璃,有 \(0.2\) 单位的光被反射回去。这 \(0.5\) 单位的光有 \(0.4\) 单位穿过第 \(2\) 层玻璃,有 \(0.025\) 单位的光被反射回去。这 \(0.025\) 单位的光有 \(0.0125\) 单位穿过第 \(1\) 层玻璃,有 \(0.005\) 单位的光被反射回去。这 \(0.005\) 单位的光有 \(0.004\) 单位穿过第 \(2\) 层玻璃……于是,穿过两层玻璃的光一共有\(0.40404... = 40/99\) 单位。在模 \(10^9+7\) 意义下等于 \(858585865\)


说实话,一读题第一反应竟是“bjoi就这?”但是,看完样例的分析我傻了,是我理解错题意了······赶紧从头又分析了一遍,感觉没问题了,便开始敲代码,结果敲了半个小时发现,好像还没有完全理解,再一次回头分析了一下样例(这提醒我们,一定要审好题,理解题意后在动手,要不然就会像我一样,浪费时间),发现第一面和最后一面的反射率是不一样的,我竟然还天真的认为反射率是一样的,不过透光率是一样的(经过计算可知),所以呢,这样就很容易了,只需要维护两个变量即可:

1、光从第 1 面玻璃射入时的透光率。

2、光从第 i 面玻璃射入时的反射率。

\(p_i=p_{i-1}a_i\sum_{k=0}^\infty(q_{i-1}b_i)^k\)

\(q_i=b_i+q_{i-1}a_i^2\sum_{k=0}^\infty(q_{i-1}b_i)^k\)

其中,还可以进一步优化:带有\(\sum_{k=0}^\infty a^k\)的形式,当\(|a|\)<1时,它等于\(\frac{1}{1-a}\)

所以:

\(P_i=\frac{P_{i-1}a_i}{1-Q_{i-1}b_i}\)

\(Q_i=b_i+\frac{Q_{i-1}a_i^2}{1-Q_{i-1}b_i}\)

可以先计算出\(\frac{1}{1-Q_{i-1}b_i}\)简化计算

最后,贴上代码:

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

完结撒花~~~~

借鉴博客:https://www.cnblogs.com/PinkRabbit/p/BJOI2019D2T2.html****

posted @ 2022-07-27 16:43  devil_恶魔  阅读(42)  评论(0)    收藏  举报