zoukankan      html  css  js  c++  java
  • bzoj4547 小奇的集合

    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;
    }
  • 相关阅读:
    数据结构学习
    古兰查询 之查询页面隐藏
    Qt只QSetting
    学习下知然网友写的taskqueue
    producter-consumer 他山之石
    unix缓冲
    Buffering of C streams
    POCO Log库
    linux下open和fopen的区别
    dup2替换
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5424791.html
Copyright © 2011-2022 走看看