zoukankan      html  css  js  c++  java
  • HDU5171 矩阵快速幂

      题目描述:http://acm.hdu.edu.cn/showproblem.php?pid=5171

     


    算法:  

      可以先将数组a[]排序,然后序列 a1 , a2 , … , an 即为有序序列,则第一次加入的就是 an + an-1 ,第二次就是 an + (an + an-1) ,如此循环就构成了斐波那契序列。

      设斐波那契序列的第k项为Fk,则可知第k次加入的即为 Fk+1 * an +  Fk * an-1

      设斐波那契序列的前k项和为Sk, 则所得结果res即为:a1 + a2 + … + an-1 + an + (Sk+1 - 1) * an + S* an-1

    实现方法:

      由于需要对结果取余,所以可以考虑用矩阵快速幂来实现斐波那契序列,具体怎么实现可以看这里

      并且根据公式可以知道 Sk = 2 * Fk + Fk-1 - 1 , 代入上式即可。

      


     

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    const int MOD = 10000007; 
    const int maxn = 100000 + 5;
    const int N = 2;
    struct Mat {
        LL mat[N][N];
    } a;
    void init()
    {
        a.mat[0][0] = a.mat[0][1] = a.mat[1][0] = 1;
        a.mat[1][1] = 0;
    }
    Mat operator *(Mat a , Mat b)
    {
        Mat tmp;
        memset(tmp.mat , 0 , sizeof(tmp.mat));
        for(int i = 0 ; i < N ; i++)
            for(int j = 0 ; j < N ; j++)
                for(int k = 0 ; k < N ; k++)
                    tmp.mat[i][j] = (tmp.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % MOD;
        return tmp;
    }
    Mat operator ^(Mat a , int k)
    {
        Mat tmp;
        for(int i = 0 ; i < N ; i++)
            for(int j = 0 ; j < N ; j++)
                tmp.mat[i][j] = (i == j);
        while(k) {
            if(k & 1)
                tmp = tmp * a;
            a = a * a;
            k /= 2;
        }
        return tmp;
    }
    LL Fib(int k)
    {
        Mat tmp;
        tmp = a ^ k;
        return tmp.mat[1][0];
    }
    LL a_[maxn];
    int main()
    {
        init();
        LL n , k , i , j , res;
        while(~scanf("%lld %lld" , &n , &k))
        {
            for(i = 1 , res = 0 ; i <= n ; i++) {
                scanf("%lld" , &a_[i]);
                res += a_[i];
            }
            sort(a_ + 1 , a_ + n + 1);
            LL tmp = ((2 * Fib(k + 1) + Fib(k) + 10000005) * a_[n] + (2 * Fib(k) + Fib(k - 1) + 10000006) * a_[n - 1]) % MOD;
            res = (res + tmp) % MOD;
            printf("%lld
    " , res);
        }
        return 0;
    }

    另外记录一个斐波那契的通项公式: ,在HDU1568中会用这个公式。

     

  • 相关阅读:
    OpenCV4学习笔记(1.0)换一种方式从源码编译、安装 | OpenCV4.3.0以及Contrib | Win10 | CMakeGUI | VS2019 | HTTP代理
    Dapr初体验之服务调用
    Dapr初体验之Hello World
    adb shell input text 中文输入方法
    记一次Mongodb数据库查询之包含所有指定元素的数组或者都在指定元素的数组中 du
    CentOS 7.2 内核3升级到4或者5
    pv
    静态 pv 和动态 pv
    k8s 编写 yaml 文件格式
    把刚升级完成的内核设置成默认启动
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4282716.html
Copyright © 2011-2022 走看看