http://vjudge.net/problem/UVA-11582
http://acdream.info/problem?pid=1060
首先证明下为什么暴力枚举n^2项以后就一定会重复。
我们说如果fib数列重复,只需要fib[i - 1] == f[0] && fib[i] == fib[1]
很明显,因为是加法,数值一样后MOD后也一定一样。所以后面的就开始循环了。
因为mod后的数的种类有n种,那么,要使得fib(i - 1) == fib(0)的概率是1 / n,那么两个都要相等的话,就是1 / (n * n)
所以,至少需要枚举n * n这么多个二元对(fib(i - 1), fib(i)),就一定会出现相等。
所以暴力枚举n * n项,一共有n * n - 1个二元对。
ABCD
ABBCCD 3个二元对。当然,可以用上fib(1),所以就是n * n对了。
hack
1、数据2^64用ULL,这个不算很大的bug
2、当MOD数是1的时候,f[1] = 0。hack
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> typedef unsigned long long int ULL; ULL fib[1000 * 1000 + 20]; ULL quick_pow(ULL a, ULL b, ULL MOD) { ULL ans = 1; ULL base = a % MOD; while (b) { if (b & 1) { ans = ans * base; if (ans >= MOD) ans %= MOD; } b >>= 1; base = base * base; if (base >= MOD) base %= MOD; } return ans; } void work() { // cout << quick_pow(2, 10, 1025) << endl; // printf("%d ", quick_pow(2, 10, 1000000)); ULL a, b, n; cin >> a >> b >> n; fib[0] = 0 % n; fib[1] = 1 % n; ULL cir = inf; for (int i = 2; i <= n * n + 3; ++i) { fib[i] = (fib[i - 1] + fib[i - 2]) % n; if (fib[i - 1] == fib[0] && fib[i] == fib[1]) { cir = i - 2 + 1; break; } } // cout << cir << "***" << endl; ULL res = quick_pow(a, b, cir); // printf("%d ", fib[res]); cout << fib[res] << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif IOS; int t; cin >> t; while (t--) work(); return 0; }