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 Fab(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 * Fab(k + 1) + Fab(k) + 10000005) * a_[n] + (2 * Fab(k) + Fab(k - 1) + 10000006) * a_[n - 1]) % MOD;
        res = (res + tmp) % MOD;
        printf("%lld\n" , res);
    }
    return 0;
}

另外记录一个斐波那契的通项公式: 

时间: 2024-08-01 11:10:57

HDU5171 矩阵快速幂的相关文章

HDU5171 GTY&#39;s birthday gift(矩阵快速幂)

Problem Description FFZ's birthday is coming. GTY wants to give a gift to ZZF. He asked his gay friends what he should give to ZZF. One of them said, 'Nothing is more interesting than a number multiset.' So GTY decided to make a multiset for ZZF. Mul

hdu5171(矩阵快速幂)

传送门:GTY's birthday gift 题意:GTY的朋友ZZF的生日要来了,GTY问他的基友送什么礼物比较好,他的一个基友说送一个可重集吧!于是GTY找到了一个可重集S,GTY能使用神犇魔法k次,每次可以向可重集中加入一个数 a+b(a,b∈S),现在GTY想最大化可重集的和,这个工作就交给你了. 注:可重集是指可以包含多个相同元素的集合 分析:想要和最大,那么每次必定从集合里面拿出最大的两个出来相加,然后k次后面就类似斐波那契数列了. 由斐波那契数列公式知:Fn=Fn-1+Fn-2,

矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423 hdu 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5587    Accepted Submission(s): 4200 Problem Description A为一个方阵,则Tr

HDU 1757 A Simple Math Problem (矩阵快速幂)

[题目链接]:click here~~ [题目大意]: If x < 10 f(x) = x. If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10); 问f(k)%m的值. [思路]:矩阵快速幂,具体思路看代码吧,注意一些细节. 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分)

POJ 3233 - Matrix Power Series ( 矩阵快速幂 + 二分) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MAX_SIZE 30 #define CLR( a, b ) memset( a, b, sizeof(a) ) int MOD = 0; int n, k; st

HDU 4990 Reading comprehension(找规律+矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4990 Problem Description Read the program below carefully then answer the question. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include<iostream> #include

hdu 6198(矩阵快速幂)

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 119 暴力发现当4 12 33 88 232 和斐波那契数列对比  答案为 第2*k+3个数减1 直接用矩阵快速幂求的F[2*k+3]  然后减1 A=1,B=0; 然后矩阵快速幂2*k

矩阵快速幂 模板与简单讲解

模板 快速幂模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,0,sizeof(e.a)); 6 7 for (int i = 0;i < d;i++) 8 e.a[i][i] = 1; 9 10 while (o) 11 { 12 if (o & 1) 13 { 14 e = mul(e,t); 15 } 16 17 o >>= 1; 18 19 t = mul(t,t); 20 } 21