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; }