【題解】LuoGu5323:[BJOI2019]光線

原題傳送門
這是一道很有趣的題目

大家都會非常直覺的想出dpdp
fif_i表示從第ii塊玻璃射出的光有多少
gig_i表示從第ii塊玻璃往前面反射回去的光有多少
得到轉移方程
fi=aifi1+bigi+1f_i=a_if_{i-1}+b_ig_{i+1}
gi=bifi1+aigi+1g_i=b_if_{i-1}+a_ig_{i+1}
又有
fn=anfn1f_n=a_nf_{n-1}
gn=bnfn1g_n=b_nf_{n-1}
感覺有點奇怪,高斯消元?
不用這麼麻煩,發現我們最重要的是fnf_ngig_i是沒有用的,嘗試消掉gig_i

Fi=fifi1F_i=\frac{f_i}{f_{i-1}}
Gi=gifi1G_i=\frac{g_i}{f_{i-1}}
又有
Fn=anF_n=a_n
Gn=bnG_n=b_n
FiGi+1=gi+1fi1F_iG_{i+1}=\frac{g_{i+1}}{f_{i-1}}
推導
fi=aifi1+bigi+1f_i=a_if_{i-1}+b_ig_{i+1}
Fi=ai+bigi+1fi1=ai+biFiGi+1F_i=a_i+b_i\frac{g_{i+1}}{f_{i-1}}=a_i+b_iF_iG_{i+1}
Fi=ai1biGi+1F_i=\frac{a_i}{1-b_iG_{i+1}}
繼續
gi=bifi1+aigi+1g_i=b_if_{i-1}+a_ig_{i+1}
Gi=bi+aigi+1fi1=bi+aiFiGi+1G_i=b_i+a_i\frac{g_{i+1}}{f_{i-1}}=b_i+a_iF_iG_{i+1}
先把Fi,GiF_i,G_i求出來之後
fi=fi1Fif_i=f_{i-1}F_i推得答案

Code:

#include <bits/stdc++.h>
#define maxn 500010
#define LL long long
using namespace std;
const LL qy = 1000000007;
int n;
LL a[maxn], b[maxn], f[maxn], F[maxn], G[maxn], inv100;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

LL ksm(LL n, LL k){
	if (!k) return 1;
	LL sum = ksm(n, k >> 1);
	sum = sum * sum % qy;
	if (k & 1) sum = sum * n % qy;
	return sum;
}

int main(){
	n = read(), inv100 = ksm(100, qy - 2);
	for (int i = 1; i <= n; ++i) a[i] = read() * inv100 % qy, b[i] = read() * inv100 % qy;
	F[n] = a[n], G[n] = b[n];
	for (int i = n - 1; i; --i)
		F[i] = a[i] * ksm((1LL - b[i] * G[i + 1] % qy + qy) % qy, qy - 2) % qy,
		G[i] = (b[i] + a[i] * F[i] % qy * G[i + 1] % qy) % qy;
	f[0] = 1;
	for (int i = 1; i <= n; ++i) f[i] = F[i] * f[i - 1] % qy;
	printf("%lld\n", f[n]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章