LGP5323 [BJTS 2019] 光线 学习笔记
LGP5323 [BJTS 2019] 光线 学习笔记
题意简述
有 \(n\) 块玻璃。对于每层玻璃 \(i\),其有一个透光率和反射率:当 \(x\) 个单位的光打到第 \(i\) 块玻璃上时,有 \(x\times a_i\%\) 单位的光透过去,有 \(x\times b_i\%\) 单位的光被反射回去,其它的光被吸收。
现在将这 \(n\) 层玻璃叠在一起,问若 \(1\) 单位的光从第 \(1\) 层玻璃上射入,最后有多少单位的光从第 \(n\) 层玻璃射出。
做法分析
这问题长得就很像个线性DP:光一层层的穿过玻璃,当光将要穿过第 \(i\) 层玻璃时,把前 \(i-1\) 层玻璃“合并”为一个玻璃去考虑看着很可做。
手玩一下此题玻璃打光的机制,我们易想到 \(P_i\) 为光从最上方射进来的透光率,\(Q_i\) 为光从下打到第 \(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
\]
我们发现里面有个无穷级数形式的东西,当 \(|a|<1\) 时,\(\sum_{k=0}^{\infty} a^k=\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)}
\]
然后算就完了!
代码实现
#include <bits/stdc++.h>
using namespace std;
namespace obasic{
typedef long long lolo;
template <typename _T>
void readi(_T &x){
_T k=1;x=0;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')k=-1;
for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-'0';
x*=k;return;
}
template <typename _T>
void writi(_T x){
if(x<0)putchar('-'),x=-x;
if(x>9)writi(x/10);
putchar(x%10+'0');
}
};
using namespace obasic;
namespace omathe{
lolo fastpow(lolo a,lolo b,lolo p){
lolo res=1;
for(;b;(a*=a)%=p,b>>=1)if(b&1)(res*=a)%=p;
return res;
}
lolo getinv(lolo a,lolo p){
return fastpow(a,p-2,p);
}
};
using namespace omathe;
const int Mod=1e9+7,MaxN=5e5+5;
const int aInv=570000004;//getinv(100,Mod)
int N;lolo A[MaxN],B[MaxN];
lolo P[MaxN],Q[MaxN],W;
int main(){
readi(N);P[0]=1,Q[0]=0;
for(int i=1;i<=N;i++){
readi(A[i]),readi(B[i]);
(A[i]*=aInv)%=Mod,(B[i]*=aInv)%=Mod;
}
for(int i=1;i<=N;i++){
W=getinv((1+Mod-(Q[i-1]*B[i]%Mod))%Mod,Mod);
P[i]=P[i-1]*A[i]%Mod*W%Mod,Q[i]=(B[i]+Q[i-1]*A[i]%Mod*A[i]%Mod*W%Mod)%Mod;
}
writi(P[N]);
return 0;
}
反思总结
无穷级数知识:当 \(|a|<1\) 时,\(\sum_{k=0}^{\infty} a^k=\frac{1}{1-a}\)。
浙公网安备 33010602011771号