P5323 [BJOI2019] 光线 题目分析
题意
当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收。
设对于任意 \(x\),有 \(x \times a_i\%\) 单位的光会穿过它,有 \(x \times b_i\%\) 的会被反射回去。
现在 \(n\) 层玻璃叠在一起,有 \(1\) 单位的光打到第 \(1\) 层玻璃上,那么有多少单位的光能穿过所有 \(n\) 层玻璃呢?
对于 \(100\%\) 的数据,\(n\le 5\times 10^5\),\(1\le a_i \le 100\),\(0\le b_i \le 99\),\(1\le a_i+b_i \le 100\)。
分析
看到这里,你要想到对于第 \(i\) 层透下去的可能从上而来,也可能是从下而来。
于是设 \(f_i\) 表示第 \(i\) 层玻璃光透下去的光照,\(g_i\) 表示从第 \(i\) 层玻璃上向上走的光照。
那么显然:
\[\begin{aligned}
f_i=f_{i-1}\cdot a_i + g_{i + 1}\cdot b_i\\
g_i=f_{i-1}\cdot b_i + g_{i+1}\cdot a_i
\end{aligned}
\]
目标是求 \(f_n\),那么我们要么老老实实高斯消元(能吗?),要么代入解方程。
有一些边界信息:\(f_n=f_{n-1}a_i,g_n=f_{n-1}b_i,g_{n+1}=0\)。
设 \(F_i=\frac{f_i}{f_{i-1}},G_i=\frac{g_i}{f_{i-1}}\)(这是因为我们要消掉 \(f_{i-1}\),才能实现倒序递推)。
代入上式并经过一些代数化简可以得到:
\[\begin{aligned}
F_i=\frac{a_i}{1-G_{i+1}b_i}\\
G_i=b_i+G_{i+1}F_i\cdot a_i
\end{aligned}
\]
从后往前推就可以了,最后令 \(f_0=1\),求 \(f_n=f_0\prod_{i=1}^nF_i\) 即可。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <cstdio>
#include <vector>
#define int long long
#define N 500005
using namespace std;
const int mod = 1e9 + 7;
int qpow(int a,int b) {
int res = 1;
while(b){
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int n,a[N],b[N],F[N],G[N];
signed main(){
cin >> n;
for (int i = 1;i <= n;i ++) scanf("%lld%lld",&a[i],&b[i]);
if (n == 1) return cout << a[1] * qpow(100,mod - 2) % mod,0;
int ans = 1,_100 = qpow(100,mod - 2);
for (int i = 1;i <= n;i ++) a[i] = a[i] * _100 % mod,b[i] = b[i] * _100 % mod;
F[n] = a[n],G[n] = b[n];
for (int i = n - 1;i;i --) {
F[i] = a[i] * qpow((1 - G[i + 1] * b[i] % mod + mod),mod - 2) % mod;
G[i] = b[i] + G[i + 1] * a[i] % mod * F[i] % mod;
}
for (int i = 1;i <= n;i ++) ans = ans * F[i] % mod;
cout << ans;
return 0;
}

浙公网安备 33010602011771号