版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34416123/article/details/82813487
有这个迷之结论
如果是比赛的话可能就打表找规律了
然后就是用矩阵快速幂了
矩阵为
1 1
1 0
很好推。
然后注意矩阵快速幂的题范围小于等于矩阵长度的时候要特判一下
同时保留后8位是模1e8, 不是1e9
#include<cstdio>
#include<cstring>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;
typedef long long ll;
const int MOD = 1e8;
struct mat
{
ll m[5][5];
mat() { memset(m, 0, sizeof(m)); }
};
mat operator * (const mat& a, const mat& b)
{
mat res;
_for(i, 1, 2)
_for(j, 1, 2)
_for(k, 1, 2)
res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
return res;
}
mat pow(mat a, ll b)
{
mat res;
_for(i, 1, 2) res.m[i][i] = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a;
a = a * a;
}
return res;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int main()
{
ll n, m;
scanf("%lld%lld", &n, &m);
ll c = gcd(n, m);
if(c <= 2) { puts("1"); return 0; }
mat A;
A.m[1][1] = A.m[1][2] = A.m[2][1] = 1;
A = pow(A, c - 2);
printf("%lld\n", (A.m[1][1] + A.m[1][2]) % MOD);
return 0;
}
上面这个方法是原始的矩阵在最后单独计算。乘法都是方阵
还有种比较复杂 写法,乘法是矩阵,但是比较通用。
#include<cstdio>
#include<cstring>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;
typedef long long ll;
const int MOD = 1e8;
struct mat
{
ll m[5][5];
int r, c;
mat() { memset(m, 0, sizeof(m)); }
};
mat operator * (const mat& a, const mat& b)
{
mat res;
_for(i, 1, a.r)
_for(j, 1, b.c)
_for(k, 1, a.c)
res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
res.r = a.r, res.c = b.c; //不要漏
return res;
}
mat pow(mat a, ll b)
{
mat res;
res.m[1][1] = res.m[1][2] = 1;
res.r = 1; res.c = 2;
for(; b; b >>= 1)
{
if(b & 1) res = res * a;
a = a * a;
}
return res;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
int main()
{
ll n, m;
scanf("%lld%lld", &n, &m);
ll c = gcd(n, m);
if(c <= 2) { puts("1"); return 0; }
mat A;
A.m[1][1] = A.m[1][2] = A.m[2][1] = 1;
A.r = A.c = 2;
A = pow(A, c - 2);
printf("%lld\n", A.m[1][1]);
return 0;
}