@loj - 2106@ 「JLOI2015」有意义的字符串


@description@

B 君有两个好朋友,他们叫宁宁和冉冉。有一天,冉冉遇到了一个有趣的题目:输入 \(b, d, n\),求:

\[\lfloor(\frac{b + \sqrt{d}}{2})^n\rfloor \mod 7528443412579576937 \]

原题戳我查看owo

@solution@

这道题的思路最早可以追溯到这一道经典题目吧。。。

注意到数据范围满足 \(b^2 \le d < (b + 1)^2\)(虽然样例不满足),这意味着 \(|\frac{b - \sqrt{d}}{2}| < 1\)

利用共轭的性质。如果我们求出 \(f(n) = (\frac{b + \sqrt{d}}{2})^n + (\frac{b - \sqrt{d}}{2})^n\) 的整数部分,则题目所要的东西实际上 = f(n) 或 f(n) - 1。

尝试递推。看到分母除 2,想到二次方程的求根公式。

\(p = (\frac{b + \sqrt{d}}{2}), q = (\frac{b - \sqrt{d}}{2})\),则 p, q 应该为方程 \(x^2 - bx + \frac{b^2 - d}{4} = 0\) 两根。

也就说有 \(p^2 = bp - \frac{b^2 - d}{4}, q^2 = bq - \frac{b^2 - d}{4}\)

然后就可以带入 f(n) 的式子里面降次,得到 f(n) 与 f(n-1),f(n-2) 的递推式子。矩阵幂即可。

-------分割线--------

当然还有另一种看起来更nb的推导方法。

我们构造 f(n) 的生成函数,记 \(F(x) = \sum_{i=0}f(i)x^i\)。则:

\[F(x) = \sum_{i=0}(\frac{b + \sqrt{d}}{2})^ix^i + \sum_{i=0}(\frac{b - \sqrt{d}}{2})^ix^i \\ = \frac{1}{1 - (\frac{b + \sqrt{d}}{2})x} + \frac{1}{1 - (\frac{b - \sqrt{d}}{2})x} \\ = \frac{2 - bx}{\frac{b^2 - d}{4}x^2 - bx + 1}\]

再对等式进行变形:

\[(\frac{b^2 - d}{4}x^2 - bx + 1)F(x) = 2 - bx \\ F(x) = -\frac{b^2 - d}{4}x^2F(x) + bxF(x) + 2 - bx \]

对应项系数比较,除 0 和 1 以外,有 \(f(n) = -\frac{b^2 - d}{4}f(n-2) + bf(n-1)\)。得到了一样的结果。

其实这就是斐波那契的通项公式的逆推导过程。

@accepted code@

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

typedef unsigned long long ull;

const ull MOD = 7528443412579576937LL;
ull add(ull A, ull B) {
	return (A + B >= MOD ? A + B - MOD : A + B);
}
ull mul(ull A, ull B) {
	ull C = 0;
	for(ull i=B;i;i>>=1,A=add(A,A))
		if( i & 1 ) C = add(C, A);
	return C;
}

ull A[2][2], R[2][2], C[2][2];
void mul(ull B[][2]) {
	C[0][0] = add(mul(B[0][0], A[0][0]), mul(B[0][1], A[1][0]));
	C[0][1] = add(mul(B[0][0], A[0][1]), mul(B[0][1], A[1][1]));
	C[1][0] = add(mul(B[1][0], A[0][0]), mul(B[1][1], A[1][0]));
	C[1][1] = add(mul(B[1][0], A[0][1]), mul(B[1][1], A[1][1]));
	B[0][0] = C[0][0], B[0][1] = C[0][1], B[1][0] = C[1][0], B[1][1] = C[1][1];
}

int main() {
	ull b, d, n;
	cin >> b >> d >> n;
	A[0][0] = b, A[0][1] = (d - b*b) / 4;
	A[1][0] = 1, A[1][1] = 0;
	R[0][0] = R[1][1] = 1, R[1][0] = R[0][1] = 0;
	for(ull i=n;i;i>>=1,mul(A))
		if( i & 1 ) mul(R);
	ull res = add(mul(b, R[1][0]), mul(2, R[1][1]));
	if( n % 2 == 0 ) {
		res = (res == 0 ? MOD - 1 : res - 1);
	}
	cout << res << endl;
} 

@details@

有一个小疑问:照这样推导下来 \(f(n) = (\frac{b + \sqrt{d}}{2})^n + (\frac{b - \sqrt{d}}{2})^n\) 一定为整数。

可是为什么。可以证明这一点吗?

posted @ 2019-12-29 22:06  Tiw_Air_OAO  阅读(198)  评论(0编辑  收藏  举报