您的位置:首页 > 其它

hdu5171 GTY's birthday gift

2015-07-20 11:11 106 查看
题意:给定一个数列含有n个数,执行k次操作(n,k<109),每次操作从中取出2个数,求和加起来在放回原数列(下一次操作对新数列进行操作) 求 最后数列可能的最大总和

分析:首先首次次操作应该选取当前数列中最大的2个数a和b (a>b) 而第二次应该选取a+b

和a 第三次 为a+b+a和a+b 这样每次新构成的数,是上一次选取的2个数之和,a和b的系数 相当于斐波那契数列。

对于快速求斐波那契数列可以构造矩阵

1 1

1 0

而这题加上对斐波那契数列的求和,所以可以构造

1 1 0

1 0 0

1 1 1

这样的矩阵 来附加求和功能

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include<stack>
#define inf 0x3f3f3f3f
#define ll long long
#define bug puts("bugbugbug");
using namespace std;
const int maxn = 20;
const int maxm = 20;
ll mod=10000007;
int a[100005];
struct Matrix {
    int n, m;
    ll a[maxn][maxm];
    void clear() {
        n = m = 0;
        memset(a, 0, sizeof(a));
    }
    Matrix operator * (const Matrix &b) const { //实现矩阵乘法
        Matrix tmp;
        tmp.n = n;
        tmp.m = b.m;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < b.m; j++) tmp.a[i][j] = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) {
                if (!a[i][j]) continue;
                for (int k = 0; k < b.m; k++)
                    tmp.a[i][k] += a[i][j] * b.a[j][k], tmp.a[i][k] %= mod;
            }

        return tmp;
    }
    void Copy(const Matrix &b) {
        n = b.n, m = b.m;
        for (int i = 0; i < n; i++)
            for(int j = 0; j < m; j++) a[i][j] = b.a[i][j];
    }
    void unit(int sz) {
        n = m = sz;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) a[i][j] = 0;
            a[i][i] = 1;
        }
    }
};
Matrix A, B,C;
Matrix Matrix_pow(Matrix A, ll k, ll mod) { //矩阵快速幂
    Matrix res;
    res.clear();
    res.n = res.m = A.n;
    for (int i = 0; i < A.n; i++) res.a[i][i] = 1;
    while(k) {
        if (k & 1) res.Copy(A * res);
        k >>= 1;
        A.Copy(A * A);
    }
    return res;
}
int main()
{
     int n,k;
     A.clear();
     A.n=A.m=3;
     A.a[0][0]=1;A.a[0][1]=1;A.a[0][2]=0;
     A.a[1][0]=1;A.a[1][1]=0;A.a[1][2]=0;
     A.a[2][0]=1;A.a[2][1]=1;A.a[2][2]=1;
    while(~scanf("%d%d",&n,&k))
    {
        int ans=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            ans=(ans+a[i])%mod;
            }
            B.clear();
       B.Copy(Matrix_pow(A,k,mod));
        C.n=3;C.m=1;
        sort(a,a+n);
        C.a[0][0]=a[n-1];
        C.a[1][0]=a[n-2];
        C.a[2][0]=0;
        C.Copy(B*C);
         printf("%d\n",(ans+C.a[2][0])%mod);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: