@loj


@description@

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

[lfloor(frac{b + sqrt{d}}{2})^n floor 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) 一定为整数。

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

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/12116685.html