题意不说了,紫书说的很清楚!
分析:
F(i) = f(i) mod n,发现是有规律的,就是有周期!
因此思路就很明确了:
1.先找到Fi的周期,因为一个n就对应一个不同的周期,但n不大 不超过1000,因此可以先打表!
2.在找到a^b是周期的第几个key ,这里可以快速幂,mod = T周期!
3.最后求F[key],因为最大是100W,所以提前打表就好了,但是想练练矩阵快速幂!,但是用矩阵快速幂错了好几次!
用矩阵快速幂需要注意几点:
1.这里的mod变了 变成n了因为是取模n嘛,所以%n,
2.通过矩阵快速幂求出的结果不一定是正确的,一定要在取模一次!(T T,坑死了。)
注意:
打表时,n要从2开始,因为1没意义,如果是1的话 一取模全是0,因此直接在输入时判断if(a == 0 || n == 1)cout << "0\n";
代码如下:
#include<iostream> #include<cstdio> #include<cmath> #include<vector> using namespace std; typedef unsigned long long llu; llu mod; llu cyc[1005]; vector<llu>fib; struct Mar{ llu mat[2][2]; }E = {1,0,0,1},D = {0,1,1,1}; llu my_pow(llu a,llu n){ llu ans =1; while(n){ if (n & 1) ans = ((ans % mod) * (a % mod)) % mod; n/=2; a= ((a % mod)*(a%mod)) % mod; } return ans; } Mar mul(Mar a, Mar b){ Mar ans={0,0,0,0}; for (int i = 0; i <2; ++i) for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) ans.mat[i][j] += ((a.mat[i][k]%mod) *( b.mat[k][j]%mod)) % mod; return ans; } Mar pow2(Mar a,llu n){ Mar ans = E; while(n){ if(n & 1) ans = mul(ans,a); n/=2; a=mul(a,a); } return ans; } int main() { for (int n = 2; n <= 1000 ;++n){ fib.clear(); fib.push_back(0); fib.push_back(1); for (int i = 2; ; ++i){ fib.push_back((fib[i-1]+fib[i-2]) % n); if (fib[i] == 1 && fib[i-1] == 0){ cyc[n]=(llu)i-1; break; } } } llu h; cin >> h; while(h--){ llu a,b,n; cin >> a >> b >> n; if (n == 1 || !a){cout << "0" <<endl;continue;} llu T = cyc[n]; mod = T; llu key = my_pow(a,b); mod = n; llu fn = pow2(D,key).mat[0][1]%mod; cout << fn << endl; } return 0; }