HDOJ-5171-GTY's birthday gift

       矩阵快速幂。题意:在一个有n个整数元素的集合S中,你可以做操作:选择集合S的两个元素a和b,把a+b放进集合S中。这种操作只能够做k次,要求做完后集合S里所有元素的和最大。输出S里所有元素的和模10000007的结果。


       我的解题思路:首先肯定是选择S里面最大的两个元素合并再添加到S集合中,假设一开始S的最大两个元素是a和b。那么第一次添加到S集合的元素是a+b,第二次是a+2b,第三次是2a+3b,第四次是3a+5b。如果用f(n)来表示斐波那契数列第n项的值的话,那么第n次操作添加的元素是f(n)a+f(n+1)b。根据斐波那契数列前n项和等于第n+2项-1的结果可以用矩阵快速幂求出求出一共添加了多少个a和b。最后就可以求和了。


       我的解题代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <climits>
#include <algorithm>

using namespace std;

typedef long long Long;

const Long MOD = 10000007;
const Long N = 2;

struct matrix
{
    Long n, m;
    Long mat[N][N];
    matrix(): n(0), m(0) {}
    matrix(Long nn, Long mm): n(nn), m(mm) {}
    void Unit(Long unit)
    {
        n = m = unit;
        for (Long i=0; i<n; ++i)
            for (Long j=0; j<m; ++j)
                mat[i][j] = i == j ? 1 : 0;
    }
};

pair<Long, Long> maxnum;
matrix init(1, 2), coef(2, 2);
Long n, k;
Long ans;

void InitRead();

void DataProcess();

matrix MatrixMul(matrix a, matrix b, Long mod);

matrix FastPow(matrix base, Long n, Long mod);

int main()
{
    while (~scanf("%lld %lld", &n, &k))
    {
        InitRead();
        DataProcess();
    }
    return 0;
}

void InitRead()
{
    maxnum.first = maxnum.second = ans = 0;
    coef.mat[0][0] = 0;
    coef.mat[0][1] = coef.mat[1][0] = coef.mat[1][1] = 1;
    init.mat[0][0] = init.mat[0][1] = 1;
    Long tmp;
    while (n--)
    {
        scanf("%lld", &tmp);
        ans += tmp;
        if (tmp > maxnum.second)
        {
            maxnum.second = tmp;
            if (maxnum.first < maxnum.second) swap(maxnum.first, maxnum.second);
        }
    }
    ans -= maxnum.first;
    ans %= MOD;
    return;
}

void DataProcess()
{
    matrix res = MatrixMul(init, FastPow(coef, k+1, MOD), MOD);
    ans += (res.mat[0][0] - 1) * maxnum.second % MOD;
    ans %= MOD;
    ans += (res.mat[0][1] - 1) * maxnum.first % MOD;
    ans %= MOD;
    printf("%lld\n", ans);
    return;
}

matrix MatrixMul(matrix a, matrix b, Long mod)
{
    matrix res(a.n, b.m);
    for (int i=0; i<res.n; ++i)
    {
        for (int j=0; j<res.m; ++j)
        {
            res.mat[i][j] = 0;
            for (int l=0; l<a.m; ++l)
            {
                res.mat[i][j] += a.mat[i][l] * b.mat[l][j];
            }
            res.mat[i][j] %= mod;
        }
    }
    return res;
}

matrix FastPow(matrix base, Long n, Long mod)
{
    matrix res;
    res.Unit(base.n);
    while (n)
    {
        if (n & 1) res = MatrixMul(res, base, mod);
        base = MatrixMul(base, base, mod);
        n >>= 1;
    }
    return res;
}


猜你喜欢

转载自blog.csdn.net/JZQT_T/article/details/44626165