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";
}
本文来自博客园,作者:CuteNess,转载请注明原文链接:https://www.cnblogs.com/CuteNess/p/19121260

浙公网安备 33010602011771号