题目
Description
Input
第一行两个整数
n
n
n,
a
a
a,含义如题所示。
为了避免输入量过大,第二行五个整数
b
x
bx
bx,
b
y
by
by,
c
x
cx
cx,
c
y
cy
cy,
p
p
p,按照下列代码来生成
b
b
b和
c
c
c数组。
b[0]=by+1;c[0]=cy+1;
for(int i=1;i<n;i++){
b[i]=((long long)b[i-1]*bx+by)%p+1;
c[i]=((long long)c[i-1]*cx+cy)%p+1;
}
Output
输出一行一个整数,表示期望花费。
Sample Input1
0 6432
4602677 3944535 2618884 6368297 9477531
Sample Input2
1 3639650
6136976 5520115 2835750 9072363 9302097
Sample Input3
10 2
2 33 6 66 2333333
Sample Input4
200 5708788
0 0 0 0 1
Sample Output1
6432
Sample Output2
150643649
Sample Output3
976750710
Sample Output4
696441597
Data Constraint
分析
考试的时候发现解决了
n
=
1
n=1
n=1的情况就可以得60分(
p
=
1
p=1
p=1的时候输出
n
=
1
n=1
n=1的结果即可),所以从
n
=
1
n=1
n=1的情况入手。考虑只要有任意两个零级合成成功了就有了一级剑,否则就会少一个零级剑,少了一个零级剑就必须多买一个零级剑,那么
n
=
1
n=1
n=1的期望就很简单了:
E
=
2
a
⋅
p
+
3
a
⋅
(
1
−
p
)
⋅
p
+
4
a
⋅
(
1
−
p
)
2
⋅
p
+
⋯
E=2a\cdot p+3a\cdot(1-p)\cdot p+4a\cdot(1-p)^2\cdot p+\cdots
E=2a⋅p+3a⋅(1−p)⋅p+4a⋅(1−p)2⋅p+⋯
其中
p
p
p是合成成功的概率,即
min
{
c
0
,
b
0
}
c
0
\dfrac{\min\{c_0,b_0\}}{c_0}
c0min{c0,b0}。
表示买两把零级剑就合成成功,买三把合成成功,买四把合成成功……的情况。
提个
a
p
ap
ap:
E
=
a
p
lim
n
→
+
∞
[
2
+
3
(
1
−
p
)
+
4
(
1
−
p
)
2
+
5
(
1
−
p
)
3
+
⋯
+
n
(
1
−
p
)
n
−
2
]
E=ap\lim_{n\to +\infty}\left[2+3(1-p)+4(1-p)^2+5(1-p)^3+\cdots+n(1-p)^{n-2}\right]
E=apn→+∞lim[2+3(1−p)+4(1−p)2+5(1−p)3+⋯+n(1−p)n−2]
设
t
=
1
−
p
t=1-p
t=1−p,要化简的就是
S
=
lim
n
→
+
∞
(
2
+
3
t
+
4
t
2
+
5
t
3
+
⋯
+
n
t
n
−
2
)
S=\lim_{n\to +\infty}(2+3t+4t^2+5t^3+\cdots+nt^{n-2})
S=n→+∞lim(2+3t+4t2+5t3+⋯+ntn−2)
等比数列错位相减:
(
t
−
1
)
S
=
lim
n
→
+
∞
[
(
2
t
+
3
t
2
+
4
t
3
+
5
t
4
⋯
+
n
t
n
−
1
)
−
(
2
+
3
t
+
4
t
2
+
5
t
3
⋯
+
n
t
n
−
2
)
]
=
lim
n
→
+
∞
(
n
t
n
−
1
−
∑
i
=
1
n
−
2
t
i
−
2
)
=
lim
n
→
+
∞
(
n
t
n
−
1
−
t
n
−
1
−
t
t
−
1
−
2
)
S
=
lim
n
→
+
∞
(
n
t
n
−
1
−
t
n
−
1
−
t
t
−
1
−
2
)
t
−
1
\begin{aligned} (t-1)S&=\lim_{n\to +\infty}\left[(2t+3t^2+4t^3+5t^4\cdots+nt^{n-1})-(2+3t+4t^2+5t^3\cdots+nt^{n-2})\right]\\ &=\lim_{n\to +\infty}(nt^{n-1}-\sum\limits_{i=1}^{n-2}t^i-2)\\ &=\lim_{n\to +\infty}(nt^{n-1}-\dfrac{t^{n-1}-t}{t-1}-2)\\\\ S&=\dfrac{\lim\limits_{n\to +\infty}(nt^{n-1}-\dfrac{t^{n-1}-t}{t-1}-2)}{t-1} \end{aligned}
(t−1)SS=n→+∞lim[(2t+3t2+4t3+5t4⋯+ntn−1)−(2+3t+4t2+5t3⋯+ntn−2)]=n→+∞lim(ntn−1−i=1∑n−2ti−2)=n→+∞lim(ntn−1−t−1tn−1−t−2)=t−1n→+∞lim(ntn−1−t−1tn−1−t−2)
显然
t
<
1
t<1
t<1,所以
lim
n
→
+
∞
n
t
n
−
1
=
0
\lim\limits_{n\to +\infty}nt^{n-1}=0
n→+∞limntn−1=0,
lim
n
→
+
∞
t
n
−
1
=
0
\lim\limits_{n\to +\infty}t^{n-1}=0
n→+∞limtn−1=0,于是
S
=
t
−
2
(
t
−
1
)
2
=
1
−
p
−
2
(
1
−
p
−
1
)
2
=
p
+
1
p
2
S=\dfrac{t-2}{(t-1)^2}=\dfrac{1-p-2}{(1-p-1)^2}=\dfrac{p+1}{p^2}
S=(t−1)2t−2=(1−p−1)21−p−2=p2p+1
所以 E = a p ⋅ p + 1 p 2 = a p + 1 p E=ap\cdot\dfrac{p+1}{p^2}=a\dfrac{p+1}{p} E=ap⋅p2p+1=app+1
在这个基础上考虑DP,设 d p [ i ] dp[i] dp[i]表示合成 i i i( i > 1 i>1 i>1)级剑的期望花费,如果合成失败,相当于少了一把 i − 1 i-1 i−1级剑,而对 i − 2 i-2 i−2级剑没有影响,从概率上来说合成 1 p \dfrac{1}{p} p1( p p p是 i i i级剑合成成功的概率)次,就能合成成功,所以就要消耗 1 p \dfrac{1}{p} p1把 i − 1 i-1 i−1级剑,一把 i − 2 i-2 i−2级剑,于是 d p [ i ] = 1 p d p [ i − 1 ] + d p [ i − 2 ] dp[i]=\dfrac{1}{p}dp[i-1]+dp[i-2] dp[i]=p1dp[i−1]+dp[i−2]
要用到逆元,每次 O ( log n ) O(\log n) O(logn)求要T,所以要预先线性打逆元表。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
int read(){
int x=0;bool f=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=x*10+(c^48),c=getchar();
return f?-x:x;
}
#define LL long long
#define MAXN 10000000
#define MOD 998244353
int N,A;
int B[MAXN+5],C[MAXN+5];
int Pow(int x,int y){
int ret=1;
while(y){
if(y&1)
ret=(LL)ret*x%MOD;
y>>=1;
x=(LL)x*x%MOD;
}
return ret;
}
#define MAXC 10000000
int Inv[MAXC+5];
void GetInv(int n){
Inv[1]=1;
for(int i=2;i<=n;i++)
Inv[i]=(LL)Inv[MOD%i]*(MOD-MOD/i)%MOD;
}
LL dp[3];//滚动数组
int main(){
freopen("forging.in" ,"r", stdin);
freopen("forging.out","w",stdout);
N=read(),A=read();
GetInv(MAXC);
int bx=read(),by=read(),cx=read(),cy=read(),p=read();
B[0]=by+1,C[0]=cy+1;
for(int i=1;i<N;i++){
B[i]=((LL)B[i-1]*bx+by)%p+1;
C[i]=((LL)C[i-1]*cx+cy)%p+1;
}
int k=min(C[0],B[0]);
int P=(LL)k*Inv[C[0]]%MOD;
dp[0]=A;
dp[1]=(LL)A*(1+P)%MOD*Pow(P,MOD-2)%MOD;
for(int i=2;i<=N;i++){
k=min(C[i-1],B[i-2]);
P=(LL)C[i-1]*Inv[k]%MOD;
dp[i%3]=(dp[(i-1)%3]*P%MOD+dp[(i-2)%3])%MOD;
}
printf("%lld",dp[N%3]);
return 0;
}