bzoj4547

矩阵乘法

看成了合并果子。。。

就是斐波那契数列,只是有负数的时候,先把负数变成正的,然后矩乘

矩乘还是用单位举矩阵记录快速幂的矩阵比较保险

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100010;
const ll mod = 10000007ll;
int n, k;
ll ans;
ll a[N];
struct mat {
    ll a[4][4];
    mat() { memset(a, 0, sizeof(a)); }
    mat friend operator * (const mat &a, const mat &b) {
        mat ret;
        memset(ret.a, 0, sizeof(ret.a));
        for(int i = 0; i < 3; ++i)
            for(int j = 0; j < 3; ++j)
                for(int k = 0; k < 3; ++k) ret.a[i][j] = (ret.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
        return ret;
    }
} A, B, tmp;
int main()
{
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]), ans = ((ans + a[i]) % mod + mod) % mod;
    sort(a + 1, a + n + 1);
    while(a[n - 1] < 0 && k) 
    {
        a[n - 1] += a[n];
        --k;
        ans = ((ans + a[n - 1]) % mod + mod) % mod;
    }   
    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; 
    B.a[0][0] = a[n];
    B.a[1][0] = a[n - 1];
    B.a[2][0] = ans;
    for(int i = 0; i < 3; ++i) tmp.a[i][i] = 1;
    for(; k; k >>= 1, A = A * A) if(k & 1) tmp = tmp * A;
    B = tmp * B;
    printf("%lld\n", (B.a[2][0] % mod + mod) % mod);
    return 0;
}
View Code

 

posted @ 2017-10-18 20:29  19992147  阅读(136)  评论(0编辑  收藏  举报