1263 广义斐波那契数列
广义斐波那契数列的定义如下:
F(0) = 1
F(1) = 1
F(n) = a * F(n - 1) + b * F(n - 2)
(a , b > 0)
广义斐波那契数列Mod N(N >= 2)会得到一个新的数列,这个数列从第0项开始,连续出现了2个1。问下一次连续出现2个1,是从数列的第几项开始。例如:
F(n) = 2 * F(n - 1) + 3 * F(n - 2)
F (mod 4) = 1 1 1 1 1 1 1... (第二次出现连续2个1是从F(1)开始)。
F (mod 5) = 1 1 0 3 1 1 0 3... (第二次出现连续2个1是从F(4)开始)。
给出a, b, n,输出下一次出现连续2个1是第几项,如果不存在下一次出现连续2个1的情况,输出-1。
输入
第1行:一个数T,表示输入的测试数量(1 <= T <= 10000)
第2 - T + 1行:每行3个数,a, b和n,中间用空格分隔(2 <= A, B < N <= 10^9)
输出
输出共T行,每行1个数,对应下一次出现连续2个1是第几项,如果不存在输出-1。
输入样例
2
2 3 4
2 3 5
输出样例
1
4
这里不放解析,只放代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
#define MP make_pair
typedef long long ll;
const int N = 1e5 + 100;
ll qpow(ll x, ll n, ll MOD) {
ll res = 1;
while (n > 0) {
if (n & 1) res = res * x % MOD;
x = x * x % MOD;
n /= 2;
}
return res;
}
int pri[N], tot;
bool is_pri[N];
void init() {
memset(is_pri, true, sizeof(is_pri));
for (int i = 2; i < N; i++) {
if (is_pri) pri[tot++] = i;
for (int j = 0; i * pri[j] < N; j++) {
is_pri[i * pri[j]] = false;
if (i % pri[j] == 0) break;
}
}
}
ll fu[2][2], co[2][2], res[2][2];
void cal(ll a[][2], ll b[][2], ll MOD) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
fu[i][j] = (fu[i][j] + a[i][k] * b[k][j]) % MOD;
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
a[i][j] = fu[i][j];
fu[i][j] = 0;
}
}
}
ll A, B;
bool check(ll n, ll MOD) {
co[0][0] = A % MOD; co[0][1] = B % MOD; co[1][0] = 1; co[1][1] = 0;
res[0][0] = res[1][1] = 1; res[1][0] = res[0][1] = 0;
while (n > 0) {
if (n & 1) cal(res, co, MOD);
cal(co, co, MOD);
n /= 2;
}
return (res[1][0] + res[1][1]) % MOD == 1 && (res[0][0] + res[0][1]) % MOD == 1;
}
ll ans, flag;
vector<pair<int, int> > V;
void fun(ll x) {
for (int i = 0; pri[i] * pri[i] <= x; i++) {
if (x % pri[i] == 0) {
int cnt = 0;
while (x % pri[i] == 0) x /= pri[i], cnt++;
V.push_back(MP(pri[i], cnt));
}
}
if (x > 1) V.push_back(MP(x, 1));
}
ll get(ll x, ll v, int c) {
ll delt = (A * A + 4 * B) % x, M = 1; V.clear();
if (delt == 0) {
V.push_back(MP(x, c));
fun(x - 1);
M = v * (x - 1);
}
else {
V.push_back(MP(x, c - 1));
fun(x - 1); fun(x + 1);
M = v / x * (x - 1) * (x + 1);
}
if (!check(M, v)) return flag = 1;
ans = 1;
sort(V.begin(), V.end());
for (int i = 0; i < V.size(); i++) {
if (i + 1 < V.size() && V[i + 1].first == V[i].first) {
V[i + 1].second += V[i].second;
continue;
}
ll r = 1, t = V[i].first, c = V[i].second;
for (int i = 1; i <= c; i++) r *= t;
int ql = 0, qr = c, qm;
while (ql < qr) {
qm = (ql + qr) / 2;
if (check(M / r * qpow(t, qm, 1e18), v)) qr = qm;
else ql = qm + 1;
}
ans *= qpow(t, ql, 1e18);
}
return ans;
}
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }
ll solve(ll n) {
ll res = 1;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
ll c = 0, r = 1;
while (n % i == 0) n /= i, r *= i, c++;
res = lcm(res, get(i, r, c));
}
}
if (n > 1) res = lcm(res, get(n, n, 1));
if (flag) return -1;
return res;
}
ll p;
int main() {
int T; scanf("%d", &T); init();
while (T--) {
scanf("%lld%lld%lld", &A, &B, &p);
flag = 0;
printf("%lld\n", solve(p));
}
return 0;
}