一般斐波切数列循环节模板

一般斐波那契数列的循环节
100
1
Case #1: 1
3
Case #2: 8
4
Case #3: 6
9
Case #4: 24
1000000007
Case #5: 2000000016
998244353
Case #6: 1996488708*/

#include 
#include 
#include 
#include 
#include 
using namespace std;

#define LL long long

const int M = 2;
struct mat {
	LL a[M][M];
};
mat A, I = {1, 0, 0, 1};
mat multi(mat a, mat b, LL mod) {
	mat ret;
	for(int i = 0; i < M; ++i)
		for(int j = 0; j < M; ++j) {
			ret.a[i][j] = 0;
			for(int k = 0; k < M; ++k)
				ret.a[i][j] = (ret.a[i][j] + a.a[i][k] * b.a[k][j]) % mod;
		}
	return ret;
}
mat qpow(mat a, LL k, LL mod) {
	mat ret = I;
	while(k) {
		if(k & 1) ret = multi(ret, a, mod);
		k >>= 1, a = multi(a, a, mod);
	}
	return ret;
}
LL gcd(LL a, LL b) {
	if(b == 0) return a;
	return gcd(b, a % b);
}
const int N = 400040;
const int NN = 5005;

LL num[NN], pri[NN], fac[NN];
int cnt, c;
bool prime[N];
int p[N], k;
void isprime() {
	k = 0;
	memset(prime, 1, sizeof(prime));
	for(int i = 2; i < N; ++i) {
		if(prime[i]) {
			p[k++] = i;
			for(int j = i + i; j < N; j += i)
				prime[j] = 0;
		}
	}
}
LL qpow(LL a, LL k, LL mod) {
	LL ret = 1;
	a %= mod;
	while(k) {
		if(k & 1) ret = ret * a % mod;
		a = a * a % mod, k >>= 1;
	}
	return ret;
}
LL legendre(LL a, LL p) {
	if(qpow(a, (p - 1) >> 1, p) == 1) return 1;
	return -1;
}
void solve(LL n, LL pri[], LL num[]) {
	cnt = 0;
	LL t = (LL)sqrt(1.0 * n);
	for(int i = 0; p[i] <= t; ++i) {
		if(n % p[i] == 0) {
			int a = 0;
			pri[cnt] = p[i];
			while(n % p[i] == 0)
				++ a, n /= p[i];
			num[cnt++] = a;
		}
	}
	if(n > 1) {
		pri[cnt] = n, num[cnt] = 1;
		++cnt;
	}
}
void work(LL n) {
	c = 0;
	LL t = (LL) sqrt(1.0 * n);
	for(int i = 1; i <= t; ++i) {
		if(n % i == 0) {
			if(i * i == n) fac[c++] = i;
			else
				fac[c++] = i, fac[c++] = n / i;
		}
	}
}
LL find_loop(LL n) {
	solve(n, pri, num);
	LL ans = 1;
	for(int i = 0; i < cnt; ++i) {
		LL record = 1;
		if(pri[i] == 2) record = 3;
		else if(pri[i] == 3) record = 8;
		else if(pri[i] == 5) record = 20;
		else {
			if(legendre(5, pri[i]) == 1)
				work(pri[i] - 1);
			else work(2 * (pri[i] + 1));
			sort(fac, fac + c);
			for(int k = 0; k < c; ++k) {
				mat a = qpow(A, fac[k] - 1, pri[i]);
				LL x = (a.a[0][0] + a.a[0][1]) % pri[i];
				LL y = (a.a[1][0] + a.a[1][1]) % pri[i];
				if(x == 1 && y == 0) {
					record = fac[k];
					break;
				}
			}
		}
		for(int k = 1; k < num[i]; ++k) record *= pri[i];
		ans = ans / gcd(ans, record) * record;
	}
	return ans;
}
void init() {
	A.a[0][0] = A.a[0][1] = A.a[1][0] = 1;
	A.a[1][1] = 0;
}
int main() {
	int cas, kk = 1;
	LL n;
	init();
	isprime();
	cin >> cas;
	while(cas--) {
		cin >> n;
		printf("Case #%d: %I64d\n", kk ++, find_loop(n));
	}
    return 0;
}

你可能感兴趣的:(斐波那契)