题意不说了,紫书说的很清楚!
分析:
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;
}