老规矩,自己去看题面
状态设计
我当时看到这道题的时候,我的第一反应竟然是:袜!这道题长得好像DP啊! 于是我开始尝试设计状态:
我们令 f [ i ] f[i] f[i] 表示经过第 i i i 层玻璃向下走的光线量, g [ i ] g[i] g[i] 表示经过第 g [ i ] g[i] g[i] 表示经过第 i i i 层玻璃向上走的光线量。
初值
根据定义我们可以得到:
f
[
0
]
=
1
,
g
[
n
+
1
]
=
0
f[0] = 1, \; g[n + 1] = 0
f[0]=1,g[n+1]=0
转移方程——可行性证明
于是我们得到转移方程 ( 为了方便表述,下列方程中
%
\%
% 均省略 ):
f
[
i
]
=
f
[
i
−
1
]
∗
a
[
i
]
+
g
[
i
+
1
]
∗
b
[
i
]
g
[
i
]
=
f
[
i
−
1
]
∗
b
[
i
]
+
g
[
i
+
1
]
∗
a
[
i
]
f[i] = f[i - 1] * a[i] + g[i + 1] * b[i] \\ g[i] = f[i - 1] * b[i] + g[i + 1] * a[i]
f[i]=f[i−1]∗a[i]+g[i+1]∗b[i]g[i]=f[i−1]∗b[i]+g[i+1]∗a[i]
然后我们就可以开开心心的转移啦 (大雾
上述式子中我们观察到式子中包含了
g
[
i
+
1
]
g[i + 1]
g[i+1] 是当前未知量 ( 如果我们是正推的话 ),并不能直接递推转移,所以我们试图消去这一未知数。
我们注意到:g当
i
=
=
n
i == n
i==n 时有:
f
[
n
]
=
f
[
n
−
1
]
∗
a
[
n
]
g
[
n
]
=
f
[
n
−
1
]
∗
b
[
n
]
f[n] = f[n - 1] * a[n] \\ g[n] = f[n - 1] * b[n]
f[n]=f[n−1]∗a[n]g[n]=f[n−1]∗b[n]
于是我们就得到了一个
f
[
n
]
f[n]
f[n] 和
g
[
n
]
g[n]
g[n] 关于
f
[
n
−
1
]
f[n - 1]
f[n−1] 的正比例函数表述形式。
我们考虑是否能将该形式推广到
i
∈
[
1
,
n
]
i \in [1, \; n]
i∈[1,n],于是我们根据原始方程写出关于
n
−
1
n - 1
n−1 的方程:
f
[
n
−
1
]
=
f
[
n
−
2
]
∗
a
[
n
−
1
]
+
g
[
n
]
∗
b
[
n
−
1
]
g
[
n
−
1
]
=
f
[
n
−
2
]
∗
b
[
n
−
1
]
+
g
[
n
]
∗
a
[
n
−
1
]
f[n - 1] = f[n - 2] * a[n - 1] + g[n] * b[n - 1] \\ g[n - 1] = f[n - 2] * b[n - 1] + g[n] * a[n - 1]
f[n−1]=f[n−2]∗a[n−1]+g[n]∗b[n−1]g[n−1]=f[n−2]∗b[n−1]+g[n]∗a[n−1]
我们将
g
[
n
]
g[n]
g[n] 代入得:
f
[
n
−
1
]
=
f
[
n
−
2
]
∗
a
[
n
−
1
]
+
f
[
n
−
1
]
∗
b
[
n
]
∗
b
[
n
−
1
]
(
1
)
g
[
n
−
1
]
=
f
[
n
−
2
]
∗
b
[
n
−
1
]
+
f
[
n
−
1
]
∗
b
[
n
]
∗
a
[
n
−
1
]
(
2
)
f[n - 1] = f[n - 2] * a[n - 1] + f[n - 1] * b[n] * b[n - 1] \;\;\;\;\; (1) \\ g[n - 1] = f[n - 2] * b[n - 1] + f[n - 1] * b[n] * a[n - 1] \;\;\;\;\; (2)
f[n−1]=f[n−2]∗a[n−1]+f[n−1]∗b[n]∗b[n−1](1)g[n−1]=f[n−2]∗b[n−1]+f[n−1]∗b[n]∗a[n−1](2)
我们将
(
1
)
(1)
(1) 式移项后合并同类项得:
f
[
n
−
1
]
∗
(
1
−
b
[
n
]
∗
b
[
n
−
1
]
)
=
f
[
n
−
2
]
∗
a
[
n
−
1
]
f[n - 1] * (1 - b[n] * b[n - 1]) = f[n - 2] * a[n - 1]
f[n−1]∗(1−b[n]∗b[n−1])=f[n−2]∗a[n−1]
再把因数除过去得:
f
[
n
−
1
]
=
f
[
n
−
2
]
∗
a
[
n
−
1
]
1
−
b
[
n
]
∗
b
[
n
−
1
]
(
3
)
f[n - 1] = f[n - 2] * \frac{a[n - 1]}{1 - b[n] * b[n - 1]} \;\;\;\;\;(3)
f[n−1]=f[n−2]∗1−b[n]∗b[n−1]a[n−1](3)
将上式代入
(
2
)
(2)
(2) 式可得:
g
[
n
−
1
]
=
f
[
n
−
2
]
∗
b
[
n
−
1
]
+
f
[
n
−
2
]
∗
a
[
n
−
1
]
1
−
b
[
n
]
∗
b
[
n
−
1
]
∗
b
[
n
]
∗
a
[
n
−
1
]
g[n - 1] = f[n - 2] * b[n - 1] + f[n - 2] * \frac{a[n - 1]}{1 - b[n] * b[n - 1]} * b[n] * a[n - 1]
g[n−1]=f[n−2]∗b[n−1]+f[n−2]∗1−b[n]∗b[n−1]a[n−1]∗b[n]∗a[n−1]
合并同类相得:
g
[
n
−
1
]
=
f
[
n
−
2
]
∗
(
b
[
n
−
1
]
+
a
[
n
−
1
]
1
−
b
[
n
]
∗
b
[
n
−
1
]
∗
b
[
n
]
∗
a
[
n
−
1
]
)
(
4
)
g[n - 1] = f[n - 2] * (b[n - 1] + \frac{a[n - 1]}{1 - b[n] * b[n - 1]} * b[n] * a[n - 1] ) \;\;\;\;\;(4)
g[n−1]=f[n−2]∗(b[n−1]+1−b[n]∗b[n−1]a[n−1]∗b[n]∗a[n−1])(4)
将
(
3
)
(
4
)
(3)(4)
(3)(4) 式换元后可得:
f
[
i
]
=
f
[
i
−
1
]
∗
a
[
i
]
1
−
b
[
i
+
1
]
∗
b
[
i
]
g
[
i
]
=
f
[
i
−
1
]
∗
(
b
[
n
−
1
]
+
a
[
i
]
1
−
b
[
i
+
1
]
∗
b
[
i
]
∗
b
[
i
+
1
]
∗
a
[
i
]
)
f[i] = f[i - 1] * \frac{a[i]}{1 - b[i + 1] * b[i]} \\ g[i] = f[i - 1] * (b[n - 1] + \frac{a[i]}{1 - b[i + 1] * b[i]} * b[i + 1] * a[i] )
f[i]=f[i−1]∗1−b[i+1]∗b[i]a[i]g[i]=f[i−1]∗(b[n−1]+1−b[i+1]∗b[i]a[i]∗b[i+1]∗a[i])
转移方程——递推方程
此时我们注意到我们已经将
∀
i
∈
[
1
,
n
]
\forall i \in[1, \; n]
∀i∈[1,n] 我们都可以表示为等比例函数形式了,于是我们想到记
F
[
i
]
=
f
[
i
]
f
[
i
−
1
]
,
G
[
i
]
=
g
[
i
]
f
[
i
−
1
]
F[i] = \frac{f[i]}{f[i - 1]}, \; G[i] = \frac{g[i]}{f[i - 1]}
F[i]=f[i−1]f[i],G[i]=f[i−1]g[i] ( 千万注意,这里的
G
G
G 中分母处是
f
f
f,看上面的方程你就知道为啥了 ) ,也就是说我们可以得到方程:
f
[
i
]
=
f
[
i
−
1
]
∗
F
[
i
]
g
[
i
]
=
f
[
i
−
1
]
∗
G
[
i
]
f[i] = f[i - 1] * F[i] \\ g[i] = f[i - 1] * G[i]
f[i]=f[i−1]∗F[i]g[i]=f[i−1]∗G[i]
注意:上面的
g
g
g 函数不是笔误,右边就是
f
f
f。
我们回到原方程中去看:
f
[
i
]
=
f
[
i
−
1
]
∗
a
[
i
]
+
g
[
i
+
1
]
∗
b
[
i
]
g
[
i
]
=
f
[
i
−
1
]
∗
b
[
i
]
+
g
[
i
+
1
]
∗
a
[
i
]
f[i] = f[i - 1] * a[i] + g[i + 1] * b[i] \\ g[i] = f[i - 1] * b[i] + g[i + 1] * a[i]
f[i]=f[i−1]∗a[i]+g[i+1]∗b[i]g[i]=f[i−1]∗b[i]+g[i+1]∗a[i]
先代入计算
f
f
f 方程可得:
f
[
i
]
=
f
[
i
−
1
]
∗
a
[
i
]
+
f
[
i
]
∗
G
[
i
+
1
]
∗
b
[
i
]
f[i] = f[i - 1] * a[i] + f[i] * G[i + 1] * b[i]
f[i]=f[i−1]∗a[i]+f[i]∗G[i+1]∗b[i]
同样的我们移项合并再除回来可得:
f
[
i
]
=
f
[
i
−
1
]
∗
a
[
i
]
1
−
G
[
i
+
1
]
∗
b
[
i
]
f[i] = f[i - 1] * \frac{a[i]}{1 - G[i + 1] * b[i]}
f[i]=f[i−1]∗1−G[i+1]∗b[i]a[i]
于是我们得到 ( 把
f
[
i
−
1
]
f[i - 1]
f[i−1] 除过去 ):
F
[
i
]
=
a
[
i
]
1
−
G
[
i
+
1
]
∗
b
[
i
]
F[i] = \frac{a[i]}{1 - G[i + 1] * b[i]}
F[i]=1−G[i+1]∗b[i]a[i]
然后我们再看
g
g
g 方程:
g
[
i
]
=
f
[
i
−
1
]
∗
b
[
i
]
+
f
[
i
]
∗
G
[
i
+
1
]
∗
a
[
i
]
⟹
g
[
i
]
=
f
[
i
−
1
]
∗
b
[
i
]
+
f
[
i
−
1
]
∗
F
[
i
]
∗
G
[
i
+
1
]
∗
a
[
i
]
⟹
g
[
i
]
=
f
[
i
−
1
]
∗
(
b
[
i
]
+
F
[
i
]
∗
G
[
i
+
1
]
∗
a
[
i
]
)
g[i] = f[i - 1] * b[i] + f[i] * G[i + 1] * a[i] \\ \implies g[i] = f[i - 1] * b[i] + f[i - 1] * F[i] * G[i + 1] * a[i] \\ \implies g[i] = f[i - 1] * (b[i] + F[i] * G[i + 1] * a[i])
g[i]=f[i−1]∗b[i]+f[i]∗G[i+1]∗a[i]⟹g[i]=f[i−1]∗b[i]+f[i−1]∗F[i]∗G[i+1]∗a[i]⟹g[i]=f[i−1]∗(b[i]+F[i]∗G[i+1]∗a[i])
于是我们得到:
G
[
i
]
=
b
[
i
]
+
F
[
i
]
∗
G
[
i
+
1
]
∗
a
[
i
]
G[i] = b[i] + F[i] * G[i + 1] * a[i]
G[i]=b[i]+F[i]∗G[i+1]∗a[i]
显然
F
[
i
]
F[i]
F[i] 我们上面已经求出了可以直接用了 ( 所以我们代码里计算顺序很重要)。
最后我们得出:
f
[
n
]
=
f
[
0
]
∗
F
[
1
]
∗
F
[
2
]
∗
.
.
.
∗
F
[
n
]
f[n] = f[0] * F[1] * F[2] * ... * F[n]
f[n]=f[0]∗F[1]∗F[2]∗...∗F[n]
这道题就到此结束了。
代码
注:以下代码中的小写 f , g f, \; g f,g 均为上述方程中的大写 F , G F, \; G F,G。
//省略快读和头文件
int pls(int x, int y)
{
if(x + y >= MOD)
return x + y - MOD;
else
return x + y;
}
int mul(int x, int y)
{
if(1ll * x * y >= MOD)
return 1ll * x * y % MOD;
else
return x * y;
}
int dec(int x, int y)
{
if(x - y < 0)
return x - y + MOD;
else
return x - y;
}
int qpow(int x, int y)
{
int val = 1;
while(y) {
if(y & 1)
val = mul(val, x);
x = mul(x, x);
y >>= 1;
}
return val;
}
int inv100;
int n;
int a[MAXN], b[MAXN];
int f[MAXN], g[MAXN];
int main()
{
inv100 = qpow(100, MOD - 2);
n = inpt();
for(int i = 1; i <= n; i++) {
a[i] = inpt(), b[i] = inpt();
a[i] = mul(a[i], inv100), b[i] = mul(b[i], inv100);
}
for(int i = n; i >= 1; i--) {
f[i] = mul(a[i], qpow(dec(1, mul(g[i + 1], b[i])), MOD - 2));
g[i] = pls(b[i], mul(f[i], mul(g[i + 1], a[i])));
}
int ans = 1;
for(int i = 1; i <= n; i++) {
ans = mul(ans, f[i]);
}
printf("%d", ans);
return 0;
}