CF193E Fibonacci Number

给定一个数 \(A\),求最小的 \(X\),使得 \(F_X\equiv A \pmod {10^{13}}\),其中 \(F_X\) 表示斐波那契数列的第 \(X\) 项,或报告无解。

\(0 \le A < 10^{13}\)


我们发现检查一个答案是否正确是非常容易的。所以我们考虑求出可能的答案的集合,然后依次检查。

我们可以选出 \(10^{13}\) 的两个大小适当的因子,分别找到在模它们意义下,斐波那契数列的循环节,和 \(A\) 出现的位置。

显然循环节不会很长,假如我们选取 \(2^{13}\)\(5^{10}\) 两个因子,他们的循环节长度分别为 \(12288\)\(7812500\)

然后做 CRT 合并两个的结果,合并后循环节的长度就是 \(\text{lcm}(12288, 7812500)\)

由于 \(\dfrac {10^{13}}{\text{lcm}(12288, 7812500)}=625\),所以只需要暴力枚举并检查即可。



#include <algorithm>
#include <iostream>
#include <vector>

typedef long long i64;
const i64 MOD = 1e13; // 10^13

struct Matrix {
	i64 x00, x01, x10, x11;
};

Matrix matrixMultiply(const Matrix& A, const Matrix& B) {
	Matrix result;
	
	result.x00 = ((__int128)A.x00 * B.x00 + (__int128)A.x01 * B.x10) % MOD;
	result.x01 = ((__int128)A.x00 * B.x01 + (__int128)A.x01 * B.x11) % MOD;
	result.x10 = ((__int128)A.x10 * B.x00 + (__int128)A.x11 * B.x10) % MOD;
	result.x11 = ((__int128)A.x10 * B.x01 + (__int128)A.x11 * B.x11) % MOD;
	
	return result;
}

Matrix _pow[64];
Matrix base = {1, 1, 1, 0};
void init() {
	_pow[0] = base;
	for(int i = 1; i < 63; ++i) {
		_pow[i] = matrixMultiply(_pow[i-1], _pow[i-1]);
	}
}

Matrix matrixPower(i64 exponent) {
	Matrix result = {1, 0, 0, 1};
	
	for(int i = 0; i < 63; ++i) {
		if(exponent >> i & 1)
			result = matrixMultiply(result, _pow[i]);
	}
	
	return result;
}

i64 calc(i64 n) {
	if (n <= 1) return 1;
	++n;
	
	Matrix result = matrixPower(n - 1);
	
	return result.x00;
}

const int p5 = 1953125; // 5^10
const int w5 = 7812500;
const int p2 = 8192; // 2^13
const int w2 = 12288;

inline std::vector<int> find(int x, int p, int w) {
	std::vector<int> vec;
	if(x == 1) vec = {0, 1};
	int a = 1, b = 1;
	for(int i = 2; i < w; ++i) {
		std::tie(a, b) = std::make_pair(b, (a + b) % p);
		if(x == b) vec.push_back(i);
	}
	return vec;
}

inline i64 solve(i64 n) {
	if(n == 1) return 1;
	
	auto work = [&](int x2, int x5) -> i64 {
		i64 _p = 0;
		for(int k = 0; k < w2; ++k) {
			i64 p = 1ll * k * w5 + x5;
			if(p % w2 == x2) {
				_p = p; break;
			}
		}
		if(!_p) return -1;
		for(int t = 0; t <= 630; ++t) {
			if(calc(_p) == n) {
				return _p + 1;
			}
			_p += 1ll * w2 * w5 / 4;
		}
		return -1;
	};
	
	auto x2s = find(n % p2, p2, w2); // p = k*w2 + x2
	auto x5s = find(n % p5, p5, w5); // p = k*w5 + x5
	
	i64 ans = 1e18;
	for(auto&& x2: x2s) {
		for(auto&& x5: x5s) {
			auto res = work(x2, x5);
			if(res != -1) ans = std::min(ans, res);
		}
	}
	
	return ans == 1e18 ? -1 : ans;
}

int main() {
	init();
	
	i64 f; std::cin >> f;
	
	i64 ans = solve(f);
	
	std::cout << (long long)ans << "\n";
}

posted @ 2025-09-30 15:33  CuteNess  阅读(8)  评论(0)    收藏  举报