[BJOI2019] 光线


题解

题解

(dp)
其实就是无限项的等比数列求和
无线项等比数列求和公式就是(frac{首项}{1-公比})
然后我们对于这道题
(p1_i)表示透光率,(p2_i)表示反射率
可以设(f_i)表示从第(i)号玻璃射出的光线数量
(g_i)表示从玻璃(i)下方射入1单位的光线最终反射回(i)的下方的光线的数量
那么可以发现(g_i=p1_i^2 imes (p2_{i-1}+g_{i-1}) + p1_i^2 imes (p2_{i-1}+g_{i-1}) imes p2_i imes (p2_{i-1} + g_{i-1})+...)
所以(g_i=frac{p1_i^2 imes (p2_{i-1}+g_{i-1})}{1-p2_i imes (p2_{i-1} + g_{i-1})})
(f_i = f_{i-1} imes p1_i + f_{i-1} imes p1_i imes p2_{i+1} imes (p2_i + g_i)))
所以(f_i=frac{f_{i-1}+p1_i}{1-p2_{i+1} imes (p2_i+g_i)})
答案就是(f_n)

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define LL long long
const int M = 500005 ;
const int mod = 1e9 + 7 ;
using namespace std ;

inline int read() {
	char c = getchar() ; int x = 0 , w = 1 ;
	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ;  }
	return x*w ;
}
int n , inv100 ;
LL p1[M] , p2[M] , f[M] , g[M] ;
inline int Fpw(int Base , int k) {
	int temp = 1 ;
	while(k) {
		if(k & 1) temp = 1LL * temp * Base % mod ;
		Base = 1LL * Base * Base % mod ; k >>= 1 ;
	}
	return temp ;
}
inline int Inv(int x) {
	x = (x % mod + mod) % mod ;
	return Fpw(x , mod - 2) ;
}
int main() {
	n = read() ; inv100 = Inv(100) ;
	for(int i = 1 ; i <= n ; i ++) {
		p1[i] = read() ; p2[i] = read() ;
		p1[i] = 1LL * p1[i] * inv100 % mod ;
		p2[i] = 1LL * p2[i] * inv100 % mod ;
	}
	f[0] = 1 ; p1[0] = 1 ; g[0] = 0 ;
	for(int i = 1 ; i <= n ; i ++) {
		g[i] = p1[i] * p1[i] % mod * (p2[i - 1] + g[i - 1]) % mod * Inv( ( 1 - p2[i] * ( p2[i - 1] + g[i - 1] ) % mod ) % mod ) % mod ;
		g[i] = (g[i] + mod) % mod ;
		f[i] = f[i - 1] * p1[i] % mod * Inv( ( 1 - p2[i + 1] * ( p2[i] + g[i] ) % mod ) % mod ) % mod ;
		f[i] = (f[i] + mod) % mod ;
	}
	printf("%lld
",f[n]) ;
	return 0 ;
}
原文地址:https://www.cnblogs.com/beretty/p/10759117.html