P5323 [BJOI2019]光线

又是一道啊

题意简述:

nn面玻璃,第ii面的透光率为aa,反射率为bb

问把这nn面玻璃按顺序叠在一起后nn层玻璃的透光率。

0<ai10 < a_i \le 10bi<10 \le b_i < 1

首先是物理题,需要一点物理题的经典思路:合并模型

考虑把n面玻璃两两合并为1面

设a1为合并过程中第1面镜子透光率,b1位第一面镜子反光率

先求新a1

  • 第一束光:a1a2a_1a_2(直接过)
  • 第二束光:a1a2b1b2a_1a_2b_1b_2(反弹一次)
  • 第三束光:a1a2b12b22a_1a_2b_1^2b_2^2反弹两次

=i=0infa1a2(b1b2)i=a1a2(1(b1b2)inf)1b1b2=\sum_{i=0}^{\inf}a_1a_2(b_1b_2)^i=\frac{a_1a_2(1-(b_1b_2)^{\inf})}{1-b_1b_2}

又因为一定收敛:

a=limn>inf....=a1a21b1b2a'=lim_{n->\inf}....=\frac{a_1a_2}{1-b_1b_2}

再求新b1

  • 第一束光:b2b_2(直接反射)

  • 第二束光: a22b1a_2^2b_1(第二块玻璃反射一次再穿越第一块两次)

  • 第三束光:a22b12b2a_2^2b_1^2b_2

    b=b2+a22b1(1(b1b2)inf)1b1b2=b2+a22b11b1b2b'=b2+\frac{a_2^{2}*b_1*(1-(b_1b_2)^{\inf})}{1-b_1b_2}=b2+\frac{a_2^2b_1}{1-b_1b_2}

    按此方法合并即可

    code:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long

namespace fastIO {
#define BUF_SIZE (1<<19)
	static char buf[BUF_SIZE],*p1=BUF_SIZE+buf,*pend=BUF_SIZE+buf;
	inline char nc() {
		if(p1==pend) {
			p1=buf;
			pend=buf+fread(buf,1,BUF_SIZE,stdin);
		}
		return *p1++;
	}

	inline int read() {
		int x=0,f=1;
		char s=nc();
		for(; !isdigit(s); s=nc())if(s=='-')f=-1;
		for(; isdigit(s); s=nc())x=(x<<1)+(x<<3)+s-'0';
		return x*f;
	}
}
using namespace fastIO;

const int P=1e9+7,inv=570000004;
//inv是100的逆元
inline ll ksm(ll x,int y) {
	ll ans=1;
	while(y) {
		if(y&1)ans=ans*x%P;
		x=x*x%P;
		y>>=1;
	}
	return ans;
}

int n,a1,a2,b1,b2,a,b,iv;

int main() {
	//freopen("test.in","r",stdin);
	n=read();
	a1=read(),a1=1ll*a1*inv%P;
	b1=read(),b1=1ll*b1*inv%P;
	while(--n) {
		a2=read();
		a2=1ll*a2*inv%P;
		b2=read();
		b2=1ll*b2*inv%P;
		iv=ksm(P+1-1ll*b1*b2%P,P-2);
		//套用公式
		a=1ll*a1*a2%P*iv%P;
		b=(b2+1ll*a2*a2%P*b1%P*iv)%P;
		a1=a,b1=b;
	}
	printf("%d\n",a1);
	return 0;
}