https://www.luogu.com.cn/problem/UVA11582
sol:
因为(a)与b的范围是ULL级别的(ULL < 2^64, LL < 2^63),所以肯定答案会循环。
当((F[i], F[i +1]))第一次重复时,那么 i 就是循环周期。二元组最多有p^2种不同的取值(抽屉原理),但是实际上只有大约i取到6 * p的时候就会开始循环。
用f[mod][i]表示再 % mod 的前提下,F[i]的值为多少。如果f[mod][i] == 1&& f[mod][i - 1] == 0,那么循环节就是i - 1。
trick:计算快速幂a^b % p时,可以先将a % p,再求快速幂。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef unsigned long long LL;
const int N = 1e3 + 100, B = 1000;
int f[N][N * 6], prid[N];
int qmi(LL a, LL b, int p) {
LL res = 1 % p;
for( ; b; b >>= 1) {
if( b & 1)
res = res * a % p;
a = a * a % p;
}
return (int)res;
}
int solve(LL a, LL b, int p) {
if(p == 1) return 0;
return f[p][qmi(a % prid[p], b, prid[p])];
}
int main() {
int T, p;
LL a, b;
for(int mod = 2; mod <= 1000; mod ++) {
f[mod][0] = 0, f[mod][1] = 1;
for(int i = 2; ; i ++) {
f[mod][i] = (f[mod][i - 1] + f[mod][i - 2]) % mod;
if( f[mod][i - 1] == 0 && f[mod][i] == 1) {
prid[mod] = i - 1;
break;
}
}
}
scanf("%d", &T);
while( T --) {
cin >> a >> b >> p;
printf("%d
", solve(a, b, p));
}
return 0;
}