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