抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

题目传送门

题意

1
2
3
4
5
6
input n
input x, t, a, b, c
for i = 1 .. n :
s_i = x
for j = 1 .. t :
x = (a * x + b) mod c

\(\sum\limits_{i=1}^{n} s_i\) 的值(不需要对 \(c\) 取模)。

\(n\le 10^6, t\le 10^9,0\le x,a,b< c\le 10^9\)

题解

考虑快速进行 for j = 1 .. t : x = (a * x + b) mod c 这段操作。

\[\begin{aligned} j=1: &\quad ax+b \\ j=2: &\quad a(ax+b)+b=a^2x+ab+b \\ j=3: & \quad a(a^2x+ab+b)+b=a^3x+a^2b+ab+b \\ j=4: & \quad a^4x+a^3b+a^2b+ab+b\\ \vdots& \\ j=t:&\quad a^tx+\sum_{k=0}^{t-1} a^kb=a^tx+b\sum_{k=0}^{t-1}a^k\end{aligned}\]

如果 \(c\) 为质数,则这个式子可以直接用快速幂和等比数列求和公式进行计算。然而并没有保证 \(c\) 是质数,怎么办呢?可以发现,\(x\)\(b\) 在这个式子中是常数,而 \(a^t\)\(\sum\limits_{k=0}^{t-1}a^k\) 有某种联系……

考虑用矩阵表示(记 \(f(t)=\sum\limits_{k=0}^{t-1}a^k\)\[A=\begin{bmatrix} a^t & f(t) \end{bmatrix},B=\begin{bmatrix} a^{t+1} & f(t+1) \end{bmatrix}\]

\(A\) 如何才能转化为 \(B\),通过计算发现:\(a^{t+1}=a\cdot a^t,f(t+1)=a^t+f(t)\),那么很显然转移矩阵为 \[C=\begin{bmatrix} a & 1\\ 0 & 1\end{bmatrix}\]

可以再验证一下 \(A\times C=B\)。于是直接用矩阵快速幂进行优化即可。

可以发现,最后 \(x\) 的转移一定可以表示为 \(px+q\) 的形式,所以只要一开始预处理 \(p,q\),不需要每次进行矩阵快速幂。

时间复杂度 \(O(n+\log t)\)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <cstdio>
#include <cstring>
int n, x, m, a, b, P;
long long ans;
struct Matrix{
int a[2][2];
Matrix operator * (const Matrix &res) const {
Matrix ret;
memset(ret.a, 0, sizeof ret.a);
for (register int i = 0; i < 2; ++i)
for (register int k = 0; k < 2; ++k)
for (register int j = 0; j < 2; ++j)
ret.a[i][j] = (ret.a[i][j] + 1ll * a[i][k] * res.a[k][j]) % P;
return ret;
}
}A, B;
Matrix qpow(Matrix a, int b){ // 矩阵快速幂
Matrix s = a;
for (--b; b; b >>= 1, a = a * a) if (b & 1) s = s * a;
return s;
}
int main(){
scanf("%d%d%d%d%d%d", &n, &x, &m, &a, &b, &P);
A.a[0][0] = a, A.a[0][1] = 1; // 初始矩阵
B.a[0][0] = a, B.a[0][1] = 1, B.a[1][0] = 0, B.a[1][1] = 1; // 转移矩阵
if (m > 1) A = A * qpow(B, m - 1);
a = A.a[0][0], b = 1ll * b * A.a[0][1] % P;
for (register int i = 1; i <= n; ++i) ans += x, x = (1ll * a * x + b) % P;
printf("%lld\n", ans);
}

upd: 修复了代码中的一个漏洞

评论