Solution -「洛谷 P2044」「NOI 2012」随机数生成器
§ Description
Link.
给你一个递推式,让你求某一项的值模上 g。
§ Solution
这道题正解是矩阵。我这里给出一种分治的做法。
题目中说
Xi=(a×Xi−1+c) mod m
我们先往下推一步
Xi−1=(a×Xi−2+c) mod m
我们把这个式子代入到原式,得到
Xi
=(a×Xi−1+c) mod m
=(a×(a×Xi−2+c)+c) mod m
=a2×Xi−2+c×(a+1) mod m
按照这个套路推下去,最后得到:
Xi=ai×X0+c×(ai−1+ai−2+⋯+a+1)
ai×X0 很好得到,直接大力快速幂,再乘上 X0 即可。
我们接着来看后面的
c×(ai−1+ai−2+⋯+a+1)
先不要看 c,即。
ai−1+ai−2+⋯+a+1
相信大家都学过因式分解,对于这样的式子进行因式分解简直再容易不过了。如果最高次为奇数次,那么我们可以直接两两分组,就可以提出来,即:
ai−1+ai−2+⋯+a+1
=(ai−1+ai−2)+(ai−3+ai−4)+⋯+(a+1)
=ai−2×(a+1)+ai−4×(a+1)+⋯+(a+1)
=(a+1)×(ai−2+ai−4+⋯+a2+1)
这样我们就可以一直递归分治下去解决问题了,最后再乘上一个 C 即可。
至于最高次为偶次就直接单独提出来大力快速幂即可。
还有一个细节,这道题的乘法常数过大,需要用“快速乘”。其实跟快速幂差不多。
#include <cstdio>
char buf[1 << 21], *p1 = buf, *p2 = buf;
#ifndef ONLINE_JUDGE
#define gc() getchar()
#else
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#endif
#define is_number (ch >= '0' && ch <= '9')
template < typename Type >
void read(Type& a) {
a = 0; bool f = 0; char ch;
while (!(ch = gc(), is_number)) if (ch == '-') f = 1;
while (is_number) a = (a << 3) + (a << 1) + (ch ^ '0'), ch = gc();
a = (f ? -a : a);
}
template < typename Type, typename... Args >
void read(Type& t, Args&... args) {
read(t), read(args...);
}
typedef long long LL;
LL MOD, a, c, X0, n, g;
LL fast_mul(LL x, LL y) {
LL res = 0;
for (; y; y >>= 1, x = (x + x) % MOD)
if (y & 1) res = (res + x) % MOD;
return res % MOD;
}
LL fast_pow(LL x, LL y) {
LL res = 1;
for (; y; y >>= 1, x = fast_mul(x, x))
if (y & 1) res = fast_mul(res, x);
return res % MOD;
}
LL get_sum(LL x, LL y) {
if (y == 0) return 1;
else if (y == 1) return (x + 1) % MOD;
else if (y & 1) return fast_mul((fast_pow(x, (y >> 1) + 1) % MOD + 1) % MOD, get_sum(x, y >> 1) % MOD) % MOD;
else return fast_mul((fast_pow(x, y >> 1) + 1) % MOD, get_sum(x, (y >> 1) - 1) % MOD) % MOD + fast_pow(x, y) % MOD;
}
signed main() {
read(MOD, a, c, X0, n, g);
X0 %= MOD;
printf("%lld\n", (fast_mul(fast_pow(a, n) % MOD, X0) % MOD + fast_mul(get_sum(a, n - 1) % MOD, c % MOD) % MOD) % MOD % g);
return 0;
}