zoukankan      html  css  js  c++  java
  • 洛谷 P1306 斐波那契公约数

    题意简述

    求斐波那契数列第n项和第m项的最大公约数

    题解思路

    设斐波那契数列第x项为F[x]
    则有结论(Gcd(F[n], F[m]) = F[Gcd(n, m)])

    证明:
    不妨设n < m
    (F[m])
    (= F[m-1] +F[m-2])
    (= 2*F[m-2] + F[m-3])
    (= 3*F[m-3] + 2*F[m-4])
    (= ......)
    (= F[x+1]*F[m-x] + F[x]*F[m-x-1])
    (= F[m-n+1]*F[n] + F[m-n]*F[n-1])
    所以
    (Gcd(F[n], F[m]))
    (= Gcd(F[n], F[m-n+1]*F[n] + F[m-n]*F[n-1]))
    (= Gcd(F[n], F[m-n]*F[n-1]))
    又因为(Gcd(F[n], F[n-1]) = Gcd(F[n-2], F[n-1]) = ...... = Gcd(F[1], F[2]) = 1)
    所以
    (Gcd(F[n], F[m]))
    (= Gcd(F[n], F[m-n]))
    同理可得
    (Gcd(F[n], F[m]))
    (= Gcd(F[n], F[m-n]))
    (= Gcd(F[n], F[m-2*n]))
    (= Gcd(F[n], F[m mod n]))
    然后可以发现,这个过程实际上就是用更相减损术求(Gcd(m, n))
    所以(Gcd(F[n], F[m]) = Gcd(F[Gcd(n, m)], F[Gcd(n, m)]) = F[Gcd(n, m)])

    最后用矩阵求出斐波那契数列第(Gcd(m, n))项即可

    代码

    #include <cstdio>
    typedef long long ll;
    const int mod = 100000000;
    int n, m, N, t;
    struct Matrix
    {
    	int a[4][4];
    	Matrix& operator =(const Matrix& x)
    	{
    		for (register int i = 1; i <= N; ++i)
    			for (register int j = 1; j <= N; ++j)
    				a[i][j] = x.a[i][j];
    		return *this;
    	}
    };
    Matrix a, b, c;
    int _gcd(int x, int y, int z = 0)
    {
    	while ((z = x % y)) x = y, y = z;
    	return y;
    }
    Matrix Mul(const Matrix& x, const Matrix& y)
    {
    	Matrix s;
    	for (register int i = 1; i <= N; ++i)
    		for (register int j = 1; j <= N; ++j)
    			s.a[i][j] = 0;
    	for (register int i = 1; i <= N; ++i)
    		for (register int j = 1; j <= N; ++j)
    			for (register int k = 1; k <= N; ++k)
    				s.a[i][j] = (s.a[i][j] + (ll)x.a[i][k] * y.a[k][j] % mod) % mod;
    	return s;
    }
    Matrix _pow(Matrix x, ll y)
    {
    	Matrix s;
    	for (register int i = 1; i <= N; ++i)
    		for (register int j = 1; j <= N; ++j)
    			s.a[i][j] = (i == j);
    	for (; y; y >>= 1, x = Mul(x, x)) if (y & 1) s = Mul(s, x);
    	return s;
    }
    int main()
    {
    	N = 3;
    	scanf("%d%d", &n, &m);
    	c.a[1][1] = c.a[1][2] = 1;
    	a.a[1][1] = a.a[1][2] = a.a[2][1] = 1;
    	n = _gcd(n, m);
    	if (n <= 2) {printf("1
    "); return 0; }
    	b = Mul(c, _pow(a, n - 2));
    	printf("%d
    ", b.a[1][1]);
    }
    
  • 相关阅读:
    洛谷P2292 [HNOI2004]L语言
    洛谷P4052 [JSOI2007]文本生成器(AC自动机)
    洛谷P3193 [HNOI2008]GT考试(KMP,矩阵)
    创建目录命令
    ssh免密码登录机器(使用公钥和秘钥进行加密来实现)
    kafka工作原理介绍
    KafKa集群安装、配置
    Kafka的partions和replication-factor参数的理解
    linux之find命令详解
    将用户需求和新型技术输入,优质服务和价值体验输出。
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9806758.html
Copyright © 2011-2022 走看看