HDU 5171 GTY's birthday gift 矩阵快速幂

题目链接:

hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5171

bc(中文): http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=567&pid=1002

题意:

给你初始的一堆数,每次从中找出两个最大的数相加再加入其中,求最后这n+k个数的和

题解:

初始堆中最大的两个数和后面的k个数会构成一个类似斐波那契数列。因此后面的和可用递推来求,由于k比较大,所以吧递推公式写成矩阵形式,用快速幂加速。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 
 7 const int maxn = 101010;
 8 const int mod = 10000007;
 9 typedef long long LL;
10 
11 struct Matrix {
12     int n, m;
13     int val[11][11];
14     Matrix(int n, int m) :n(n), m(m) {}
15     Matrix() {}
16     void init(int n, int m) { this->n = n; this->m = m; }
17     friend Matrix operator *(const Matrix& mat1, const Matrix& mat2) {
18         Matrix ret(mat1.n, mat2.m);
19         for (int i = 0; i < ret.n; i++) {
20             for (int j = 0; j < ret.m; j++) {
21                 ret.val[i][j] = 0;
22                 for (int k = 0; k < mat1.m; k++) {
23                     ret.val[i][j] += (LL)mat1.val[i][k] * mat2.val[k][j] % mod;
24                     ret.val[i][j] %= mod;
25                 }
26             }
27         }
28         return ret;
29     }
30 };
31 
32 void power(Matrix& mat, int n, Matrix& ans) {
33     while (n) {
34         if (n & 1) ans = mat*ans;
35         mat = mat*mat;
36         n /= 2;
37     }
38 }
39 
40 int arr[maxn];
41 int n, k;
42 Matrix mat, ans;
43 
44 void init() {
45     mat.init(3, 3);
46     mat.val[0][0] = 1; mat.val[0][1] = 1; mat.val[0][2] = 1;
47     mat.val[1][0] = 0; mat.val[1][1] = 1; mat.val[1][2] = 1;
48     mat.val[2][0] = 0; mat.val[2][1] = 1; mat.val[2][2] = 0;
49     ans.init(3, 1);
50     ans.val[0][0] = arr[n - 2] + arr[n - 1];
51     ans.val[1][0] = arr[n - 1];
52     ans.val[2][0] = arr[n - 2];
53 }
54 
55 int main() {
56     while (scanf("%d%d",&n,&k)==2&&n>1) {
57         for (int i = 0; i < n; i++) scanf("%d", arr + i);
58         sort(arr, arr + n);
59         LL sum = 0;
60         for (int i = 0; i < n - 2; i++) {
61             sum += arr[i]; sum %= mod;
62         }
63         init();
64         power(mat,k, ans);
65         sum = (sum + ans.val[0][0]) % mod;
66         printf("%d\n", sum);
67     }
68     return 0;
69 }

 

posted @ 2016-04-27 14:01  fenicnn  阅读(210)  评论(0编辑  收藏  举报