ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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

 

posted on 2016-04-23 15:42  nul  阅读(231)  评论(0编辑  收藏  举报