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取模。
每次应取可重集合中的两个最大值相加
若最大值均为非负数则可以利用斐波那契数列求k次操作后新增的数之和;
若最大值和次大值一正一负则每次将最大值和次大值相加直至k次操作完成或次大值非负用斐波那契数列求剩余操作。
n
Σ Fi = Fn+2-1
i=1
#include<cstdio> #include<algorithm> int n,k; const int P=10000007; int v[100005]; typedef int mat[2]; mat m1,m2; inline int input(){ int x=0,c=getchar(),f=1; while(c>57||c<48){ if(c=='-')f=-1; c=getchar(); } while(c>47&&c<58)x=x*10+c-48,c=getchar(); return x*f; } inline void mul(mat a,mat b){ int c=(1ll*(a[1]-a[0])*b[0]+1ll*a[0]*b[1])%P; int d=(1ll*a[0]*b[0]+1ll*a[1]*b[1])%P; a[0]=c;a[1]=d; } inline void fib(int x){ x+=1; m1[0]=0;m1[1]=1; m2[0]=m2[1]=1; while(x){ if(x&1)mul(m1,m2); mul(m2,m2); x>>=1; } } int Ans=0; int main(){ n=input();k=input(); for(int i=0;i<n;i++)v[i]=input(); std::nth_element(v,v+n-2,v+n); for(int i=0;i<n;i++){ Ans+=v[i]; if(Ans>=P)Ans-=P; if(Ans<P)Ans+=P; } int v1=v[n-1],v2=v[n-2]; if(v1<=0){ Ans=(Ans+(v1+v2)*1ll*k)%P; if(Ans<0)Ans+=P; printf("%d",Ans); }else if(v2<0){ while(v2<0&&k){ v2+=v1; Ans+=v2; if(Ans>=P)Ans-=P; if(Ans<P)Ans+=P; --k; } if(v2>v1)v1^=v2,v2^=v1,v1^=v2; if(k){ fib(k); int ans=((m1[1]-1)*1ll*v2+(m1[1]+m1[0]-2)*1ll*v1)%P; Ans=(Ans+ans)%P; } if(Ans<0)Ans+=P; printf("%d",Ans); }else{ fib(k); int ans=((m1[1]-1)*1ll*v2+(m1[1]+m1[0]-2)*1ll*v1)%P; Ans=(Ans+ans)%P; if(Ans<0)Ans+=P; printf("%d",Ans); } return 0; }