#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
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) % 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;
}
LL f(LL n, LL mod) {
if(n == 0 || n == 1) return 1;
mat t = qpow(A, n - 1, mod);
return (t.a[0][0] + t.a[0][1]) % mod;
}
int readint() {
char c;
while((c = getchar()) && !(c >= '0' && c <= '9'));
int ret = c - '0';
while((c = getchar()) && c >= '0' && c <= '9')
ret = (ret << 3) + (ret << 1) + c - '0';
return ret;
}
int main() {
init();
isprime();
int cas;
scanf("%d", &cas);
while(cas--) {
int n, mod;
n = readint();
mod = readint();
if(mod == 1) {
puts("0");
continue;
}
LL k1 = find_loop(mod);
LL k2 = find_loop(k1);
printf("%lld\n", f(f(f(n, k2), k1), mod));
}
return 0;
}
acdream 1124 喵喵的遗憾 fib循环节
最新推荐文章于 2021-05-19 20:19:19 发布