BZOJ4547 Hdu5171 小奇的集合 【矩阵快速幂优化递推】
BZOJ4547 Hdu5171 小奇的集合
Description
有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大值。(数据保证这个值为非负数)
Input
第一行有两个整数n,k表示初始元素数量和操作数,第二行包含n个整数表示初始时可重集的元素。
对于100%的数据,有 n<=105,k<=109,|ai|<=10^5
Output
输出一个整数,表示和的最大值。答案对10000007取模。
Sample Input
2 2
3 6
Sample Output
33
首先我们要分情况讨论
当最大值和次大值都是正数,直接用矩阵快速幂优化就可以了
当最大值是正数,次大值是负数的时候,要先把次大值加成正数再矩阵快速幂
当最大和次大都是负数的时候,可以直接算出答案
然后矩阵快速幂就很常规了,记录一下当前最大值和次大值和sum
然后转移矩阵很简单自己手推一下就好了
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define fu(a,b,c) for(int a=b;a<=c;++a) 4 #define N 100010 5 #define INF 0x3f3f3f3f 6 #define LL long long 7 #define Mod 10000007 8 struct Matrix{LL t[3][3];}; 9 Matrix mul(Matrix a,Matrix b){ 10 Matrix c; 11 memset(c.t,0,sizeof(c.t)); 12 fu(i,0,2)fu(j,0,2)fu(k,0,2) 13 c.t[i][j]=(c.t[i][j]+a.t[i][k]*b.t[k][j]%Mod+Mod)%Mod; 14 return c; 15 } 16 Matrix fast_pow(Matrix a,LL b){ 17 Matrix ans; 18 fu(i,0,2)fu(j,0,2)ans.t[i][j]=(i==j); 19 while(b){ 20 if(b&1)ans=mul(ans,a); 21 a=mul(a,a); 22 b>>=1; 23 } 24 return ans; 25 } 26 int solve(LL max1,LL max2,LL k){ 27 Matrix tmp,ans; 28 tmp.t[0][0]=1;tmp.t[0][1]=1;tmp.t[0][2]=1; 29 tmp.t[1][0]=1;tmp.t[1][1]=0;tmp.t[1][2]=1; 30 tmp.t[2][0]=0;tmp.t[2][1]=0;tmp.t[2][2]=1; 31 tmp=fast_pow(tmp,k); 32 ans.t[0][0]=max1;ans.t[0][1]=max2;ans.t[0][2]=0; 33 ans.t[1][0]=0;ans.t[1][1]=0;ans.t[1][2]=0; 34 ans.t[2][0]=0;ans.t[2][1]=0;ans.t[2][2]=0; 35 ans=mul(ans,tmp); 36 return ans.t[0][2]; 37 } 38 int main(){ 39 LL n,k,sum=0,max1=-INF,max2=-INF; 40 scanf("%lld%lld",&n,&k); 41 fu(i,1,n){ 42 LL x;scanf("%lld",&x); 43 sum=(sum+x%Mod+Mod)%Mod; 44 if(x>max1)max2=max1,max1=x; 45 else if(x>max2)max2=x; 46 } 47 if(max1>0&&max2>0)printf("%lld",(sum+solve(max1,max2,k)+Mod)%Mod); 48 else if(max1<0&&max2<0)printf("%lld",(sum+(max1+max2)*k%Mod+Mod)%Mod); 49 else{ 50 int cnt=0; 51 while(max2<0){ 52 int newv=max1+max2; 53 if(newv>max1){max2=max1,max1=newv;} 54 else{max2=newv;} 55 sum=(sum+newv)%Mod; 56 cnt++; 57 if(cnt==k)break; 58 } 59 if(cnt==k)printf("%lld",(sum+Mod)%Mod); 60 else printf("%lld",(sum+solve(max1,max2,k-cnt)+Mod)%Mod); 61 } 62 return 0; 63 }