由于斐波那契数列在模 m 意义下是有循环节的,我们可以先预处理,对于每个 m′,计算 FnFn−1modpqm′、p、q,并存储三元组 (p,q,FnFn−1modpqm′)。对于每组询问的 a、b,计算 d,并得到 a′、b′、m′。计算 p、q、−a′b′modpqm′,在存储的三元组中查找是否存在对应的项。如果存在,则找到最小的 n 使得满足条件,如果不存在,则输出 −1。
AC code
CPP
#include<bits/stdc++.h>#define int long long usingnamespace std;
constint N = 200000;
using PPIII = pair<pair<int, int>, int>;
int n, m, a, b;
map<PPIII, int> ck[N + 5];
voidexgcd(int a, int b, int &x, int &y){
if (a == 1) {
x = 1;
y = 0;
return ;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
//解方程 ax + by = 0 intinv(int x, int m){
int n, temp;
exgcd(x, m, n, temp);
return (n % m + m) % m;
}
//解同余方程求逆元 signedmain(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 2; i <= m; i ++ )
if (m % i == 0) { // 枚举 m' int x = 1, y = 0, s = 0;
while (true) { // 枚举斐波那契数列 if (x != 0 && y != 0) {
int dx = __gcd(x, i), dy = __gcd(y, i);
int mp = i / dx / dy;
int t = ((y / dy) * inv((x / dx), mp) % mp + mp) % mp;
// 存储if (!ck[i].count({{dx, dy}, t}))
ck[i][{{dx, dy}, t}] = s;
// 保存
}
int t = x;
x = y;
y = (t + y) % i;
// 计算下一对 if (x == 1 && y == 0) break;
// 循环节
s ++ ;
}
}
while(n -- ) {
cin >> a >> b;
b = (m - b) % m;
if (a == 0) {
cout << "0\n";
continue;
}
if(b == 0) {
cout << "1\n";
continue;
}
// 特殊判断 int d = __gcd(__gcd(a, b), m), mp = m / d;
a /= d; b /= d;
int p = __gcd(a, mp), q = __gcd(b, mp), mpp = mp / p / q;
a /= p, b /= q;
int k = (a * inv(b, mpp) % mpp + mpp) % mpp;
// 查询if (ck[mp].count({{q, p}, k}))
cout << ck[mp][{{q, p}, k}] << '\n';
else
cout << "-1\n";
// 查询答案
}
return0;
}