Solution -「洛谷 P2044」「NOI 2012」随机数生成器

Description

Link.

给你一个递推式,让你求某一项的值模上 \(g\)

Solution

这道题正解是矩阵。我这里给出一种分治的做法。

题目中说

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(X_{i}=(a\times X_{i-1}+c)\ \mathrm{mod}\ m\)

我们先往下推一步

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(X_{i-1}=(a\times X_{i-2}+c)\ \mathrm{mod}\ m\)

我们把这个式子代入到原式,得到

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(X_{i}\)

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(=(a\times X_{i-1}+c)\ \mathrm{mod}\ m\)

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(=(a\times(a\times X_{i-2}+c)+c)\ \mathrm{mod}\ m\)

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(=a^{2}\times X_{i-2}+c\times(a+1)\ \mathrm{mod}\ m\)

按照这个套路推下去,最后得到:

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(X_{i}=a^{i}\times X_{0}+c\times(a^{i-1}+a^{i-2}+\cdots+a+1)\)

\(a^{i}\times X_{0}\) 很好得到,直接大力快速幂,再乘上 \(X_{0}\) 即可。

我们接着来看后面的

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(c\times(a^{i-1}+a^{i-2}+\cdots+a+1)\)

先不要看 \(c\),即。

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(a^{i-1}+a^{i-2}+\cdots+a+1\)

相信大家都学过因式分解,对于这样的式子进行因式分解简直再容易不过了。如果最高次为奇数次,那么我们可以直接两两分组,就可以提出来,即:

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(a^{i-1}+a^{i-2}+\cdots+a+1\)

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(=(a^{i-1}+a^{i-2})+(a^{i-3}+a^{i-4})+\cdots+(a+1)\)

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(=a^{i-2}\times(a+1)+a^{i-4}\times(a+1)+\cdots+(a+1)\)

$\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ $\ \ \ \ \ \ \ $ \(=(a+1)\times(a^{i-2}+a^{i-4}+\cdots+a^{2}+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;
}
posted @ 2020-04-19 12:54  cirnovsky  阅读(125)  评论(0编辑  收藏  举报