$$ \text{求}F\left( n \right) \,\,mod\,\,p,n\le 10^{30000000},p\le 2^{31}-1 \\ \text{斐波那契数列在模}p\text{意义下的循环节长度为}O\left( p \right) \text{级别。} \\ \text{首先将}p\text{进行质因数分解,得到}p_{1}^{k_1}p_{2}^{k_2}p_{3}^{k_3}… \\ \text{设}T\left( k \right) \text{为模}k\text{意义下的循环节长度,则}T\left( p \right) =\prod{T\left( p_i^{k_i} \right)} \\ \text{同时对于}p^k,\text{有}T\left( p^k \right) =T\left( p \right) \times p^{k-1} \\ \text{考虑如何求出模质数的循环节长度。} \\ \text{对于2,3,5直接特判。} \\ \text{对于其他质数}p\text{,如果5是模}p\text{意义下的二次剩余}\left( \text{即}5^{\frac{p-1}{2}}\equiv 1\left( mod\,\,p \right) \right) ,\text{则模}p\text{意义下的循环节长度是}p-\text{1的约数。} \\ \text{部分证明:} \\ \text{斐波那契数列的通项公式为}F_n=\frac{\sqrt{5}}{5}\left( \left( \frac{\left( 1+\sqrt{5} \right)}{2} \right) ^n-\left( \frac{\left( 1-\sqrt{5} \right)}{2} \right) ^n \right) \\ \text{设5在模}p\text{意义下的二次剩余为}x\text{,则}F_n\text{一定可以表示为}k\left( x_0^n-x_1^n \right) \text{的形式。} \\ \text{其中}x_0^n\text{和}x_1^n\text{的周期一定是}\varphi \left( p \right) \text{的约数。} \\ \text{故}F_n\text{的周期是}\varphi \left( p \right) \text{的约数。} \\ \\ \text{反之,模}p\text{意义下的循环节长度是}2\left( p+1 \right) \text{的约数。} \\ \text{枚举约数验证即可。} \\ \text{这个我不会证} \\ \\ $$
#include <climits>
#include <cstring>
#include <iostream>
#include <map>
using int_t = long long int;
using std::cin;
using std::cout;
using std::endl;
struct Matrix mat_mul(const struct Matrix& a, const struct Matrix& b,
int_t mod);
int_t power(int_t base, int_t index, int_t mod);
struct Matrix {
int_t data[4][4];
Matrix() { memset(data, 0, sizeof(data)); }
int_t& operator()(int_t r, int_t c) { return data[r][c]; }
const int_t N = 2;
Matrix& operator=(const Matrix& mat2) {
memcpy(data, mat2.data, sizeof(data));
return *this;
}
Matrix power(int_t index, int_t mod) {
Matrix result;
Matrix base = *this;
result(1, 1) = result(2, 2) = 1;
while (index) {
if (index & 1) result = mat_mul(result, base, mod);
base = mat_mul(base, base, mod);
index >>= 1;
}
return result;
}
};
Matrix mat_mul(const Matrix& a, const Matrix& b, int_t mod) {
const auto N = a.N;
Matrix result;
for (int_t i = 1; i <= N; i++) {
for (int_t j = 1; j <= N; j++) {
for (int_t k = 1; k <= N; k++) {
result.data[i][j] =
(result.data[i][j] + a.data[i][k] * b.data[k][j] % mod) %
mod;
}
}
}
return result;
}
Matrix F(int_t k, int_t mod) {
Matrix mat;
mat(1, 1) = 0;
mat(1, 2) = 1;
mat(2, 1) = 1;
mat(2, 2) = 1;
return mat.power(k, mod);
}
//计算模p意义下的循环周期,p是质数
int_t getPeriod(int_t p) {
if (p == 2)
return 3;
else if (p == 3)
return 8;
else if (p == 5)
return 20;
int_t fac;
if (power(5, (p - 1) / 2, p) == 1) {
fac = p - 1;
} else {
fac = 2 * (p + 1);
}
const auto check = [&](int_t x) -> bool {
Matrix res = ::F(x + 1, p);
return res(1, 1) == 0 && res(1, 2) == 1;
};
int_t result = 1e12;
for (int_t i = 1; i * i <= fac; i++) {
if (fac % i == 0) {
if (i != 1 && check(i)) {
result = std::min(result, i);
}
if (fac / i != i && check(fac / i)) {
result = std::min(result, fac / i);
}
}
}
return result;
}
std::map<int_t, int_t> divide(int_t x) {
std::map<int_t, int_t> result;
for (int_t i = 2; i * i <= x; i++) {
if (x % i == 0) {
result[i] = 0;
while (x % i == 0) {
x /= i;
result[i]++;
}
}
}
if (x > 1) result[x] += 1;
return result;
}
int main() {
static char buf[30000000 + 10];
scanf("%s", buf);
int_t p;
cin >> p;
int_t length = 1;
for (const auto& pair : divide(p)) {
length *= ::getPeriod(pair.first) *
power(pair.first, pair.second - 1, int_t(1) << 40);
}
int_t sum = 0;
for (auto ptr = buf; *ptr != '\0'; ptr++) {
sum = (sum * 10 + *ptr - '0') % length;
}
cout << F(sum , p)(1, 2) << endl;
return 0;
}
int_t power(int_t base, int_t index, int_t mod) {
int_t result = 1;
while (index) {
if (index & 1) result = result * base % mod;
index >>= 1;
base = base * base % mod;
}
return result;
}
发表回复