bzoj 4547 小奇的集合

Description

 有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大

值。(数据保证这个值为非负数)

Input

第一行有两个整数n,k表示初始元素数量和操作数,第二行包含n个整数表示初始时可重集的元素。

对于100%的数据,有 n<=10^5,k<=10^9,|ai|<=10^5

Output

输出一个整数,表示和的最大值。答案对10000007取模。

Sample Input

2 2
3 6

Sample Output

33
显然可以把原数组排序,新元素就是最后2项之和
但是原题只保证答案是非负数,所以会有小于0的情况
而且不会出现最大和次大都是负数,最多就是最大为正,次大为负
相加直到两个数都为正数
然后就可以矩阵快速幂
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long lol;
 8 lol Mod=1e7+7;
 9 struct Matrix
10 {
11     lol a[4][4];
12 } ans,Mat;
13 lol n,a[100005],k,sum;
14 Matrix operator *(const Matrix &a,const Matrix &b)
15 {
16     lol i,j,l;
17     Matrix res;
18     memset(res.a,0,sizeof(res.a));
19     for (i=1; i<=3; i++)
20     {
21         for (j=1; j<=3; j++)
22         {
23             for (l=1; l<=3; l++)
24             {
25                 res.a[i][j]+=a.a[i][l]*b.a[l][j]%Mod;
26                 res.a[i][j]=(res.a[i][j]%Mod+Mod)%Mod;
27             }
28         }
29     }
30     return res;
31 }
32 Matrix qpow(lol y)
33 {
34     lol i;
35     Matrix res;
36     memset(res.a,0,sizeof(res.a));
37     for (i=1; i<=3; i++)
38         res.a[i][i]=1;
39     while (y)
40     {
41         if (y&1) res=res*Mat;
42         Mat=Mat*Mat;
43         y>>=1;
44     }
45     return res;
46 }
47 int main()
48 {
49     lol i;
50     cin>>n>>k;
51     for (i=1; i<=n; i++)
52     {
53         scanf("%lld",&a[i]);
54         sum=(sum+a[i])%Mod;
55     }
56     sort(a+1,a+n+1);
57     if (k==0)
58     {
59         cout<<sum;
60         return 0;
61     }
62     if (a[n-1]<0)
63     {
64         a[n+1]=(a[n]+a[n-1]);
65         n++;
66         k--;
67         sum=(sum+a[n]%Mod)%Mod;
68         swap(a[n],a[n-1]);
69     }
70     ans.a[1][1]=0;
71     ans.a[1][2]=(a[n]+Mod)%Mod;
72     ans.a[1][3]=(a[n-1]+Mod)%Mod;
73     Mat.a[1][1]=1;
74     Mat.a[2][1]=1;
75     Mat.a[3][1]=1;
76     Mat.a[2][2]=1;
77     Mat.a[3][2]=1;
78     Mat.a[2][3]=1;
79     ans=ans*qpow(k);
80     cout<<((sum+ans.a[1][1])%Mod+Mod)%Mod;
81 }
82 

 

posted @ 2018-03-24 09:40  Z-Y-Y-S  阅读(331)  评论(0编辑  收藏  举报