题目大意
有如下两个操作
- 花费(a)购买一把(0)级的剑
- 将一把(x)级的剑与一把(max(x-1,0))级的剑进行锻造,有(p)的概率成功,然后得到一把(x+1)级的剑,若失败,得到一把(max(x-1,0))级的剑
求得到一把(n)级的剑的期望花费。
分析
首先明确一点,假如你要得到(x)级的剑,不用考虑它是失败后得到的(因为你有了(x)还和(x+1)去锻造不是白给吗?(逐渐茄化)),因此只用考虑(x)由(x-1)和(x-2)锻造得来的期望花费。
设(f_i)表示弄到一把(i)级的剑的期望花费,得到递推式:
[f_i=f_{i-2}+f_{i-1}+sum_{k=1}^{infty}(1-p)^k f_{i-1}
]
这个式子怎么解释呢?你想锻造(i),弄到(i-1)和(i-2)的花费是必不可少的,若你失败了,(i-2)还在,你要买的只是(i-1)。你可以失败无数次,于是就得到上面的式子。一波化简后得到:
[f_i=f_{i-2}+frac{f_{i-1}}{p}
]
线性求逆元然后优化优化常数就是一道好题了。
Code
#include <cstdio>
typedef long long ll;
const int N = 10000007, P = 998244353;
int min(int a, int b)
{
if (a < b) return a;
return b;
}
int n, a, bx, by, cx, cy, p, u, v, w, i, k;
int b[N], c[N], inv[N];
int main()
{
freopen("forging.in", "r", stdin);
freopen("forging.out", "w", stdout);
scanf("%d%d%d%d%d%d%d", &n, &a, &bx, &by, &cx, &cy, &p);
b[0] = by + 1, c[0] = cy + 1;
for (i = 1; i < n; ++i) b[i] = (1ll * b[i - 1] * bx % p + by) % p + 1, c[i] = (1ll * c[i - 1] * cx % p + cy) % p + 1;
inv[1] = 1; for (i = 2; i <= p; ++i) inv[i] = 1ll * inv[P % i] * (P - P / i) % P;
u = a, v = (u + 1ll * u * inv[min(c[0], b[0])] % P * c[0] % P) % P;
if (n == 0) printf("%d
", u);
else
{
for (i = 2, k; i <= n; ++i) k = min(c[i - 1], b[i - 2]), w = (u + 1ll * v * inv[k] % P * c[i - 1] % P) % P, u = v, v = w;
printf("%d
", v);
}
return 0;
}