51nod1263 广义斐波那契数列

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;
}

猜你喜欢

转载自blog.csdn.net/ZCH1901/article/details/120388229
今日推荐