Luogu P1306 斐波那契公约数

这道题其实是真的数学巨佬才撸的出来的题目了

但如果只知道结论但是不知道推导过程的我感觉证明无望

首先这道题肯定不能直接搞,而且题目明确说明了一些方法的问题

所以就暗示我们直接上矩阵了啦

但是如果直接搞还要高精度,不仅很烦而且绝壁TLE

所以我们引出性质,其中f[x]表示斐波那契数列的第x项:

gcd(f[n],f[m])=f[gcd(n,m)]

具体的超详细的证明戳这里

然后题意相当于对f[gcd(n,m)]取膜1e9,就是最基本的矩阵优化了

关于矩阵优化斐波那契的板子题看这里

关于这题的CODE,因为那天晚上在Linux机子上打的,被强制转码风了,而且Tab还是两个空格

CODE

#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=3,mod=1e8;
int n,m;
struct Matrix{
  int n,m;
  LL a[N][N];
  inline void Fb_init(void){
    n=m=2; a[1][1]=0; a[1][2]=a[2][1]=a[2][2]=1;
  }
  inline void cri_init(void){
    n=m=2; a[1][1]=a[2][2]=1; a[1][2]=a[2][1]=0;
  }
};
inline Matrix mul(Matrix A,Matrix B){
  Matrix C; C.n=A.n; C.m=B.m; memset(C.a,0,sizeof(C.a));
  for (register int i=1;i<=C.n;++i)
    for (register int j=1;j<=C.m;++j)
      for (register int k=1;k<=A.m;++k)
    C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
  return C;
}
inline Matrix quick_pow(Matrix A,int p){
  Matrix T; T.cri_init();
  while (p){
    if (p&1) T=mul(T,A);
    A=mul(A,A); p>>=1;
  }
  return T;
}
inline int gcd(int n,int m){
  return m?gcd(m,n%m):n;
}
int main(){
  //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
  scanf("%d%d",&n,&m); n=gcd(n,m);
  if (n<=2) { puts("1"); return 0; }
  Matrix A; A.Fb_init();
  A=quick_pow(A,n-2);
  printf("%lld",(A.a[2][1]+A.a[2][2])%mod);
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/cjjsb/p/9082334.html
今日推荐