zoukankan      html  css  js  c++  java
  • BZOJ 4547: Hdu5171 小奇的集合

    Sol

    首先,考虑这个要怎么搞...让总和最大的方法就是选出当前集合中最大的两个数相加放入集合中就可以了,证明非常简单,当前集合的和为x,它的和只会一直往后增加,所以只需要找到最大的两个数的和加入便是最佳答案.知道了这个以后,手动递推一下就是一个斐波拉契数列.

    然后斐波拉契数列数列自然可以矩乘,但是矩阵乘法不能解决负数斐波拉契问题.而且,一正一负就不是斐波拉契数列的递推了.递推应该是这个样子.

    (F_2=F_1+F_0,F_3=F_2+F_1=F_1+F_1+F_0...F_n=F_1*(n-1)+F_0)

    所以我们就可以直接 (O(1)) 得到需要进行多少次操作使得出现两个正数,原来的 (F_1) 就已经是一个正数了,所以操作数为 (left lfloor -F_0/F_1 ight floor +1) 求和用等差数列求和公式,剩下的直接矩乘.

    剩下的问题就是斐波拉契数列求和的问题了,我们知道斐波拉契数列前n项和 (sum_{i=0}^{n}F_i=F_{n+2}-1) 虽然这个前两项并不是1,但是可以得到相似的结论 (sum_{i=0}^{n}F_i=F_{n+2}-F_1) .

    在这里我给出证明,证明也很简单,数学归纳法.

    证明: (n=0) 时显然成立, (F_0=F_2-F_1) 移项一下就是递推式

    当 (n>0) 时,假设有 (sum_{i=0}^{n}F_i=F_{n+2}-F_1)

    只需要证明在 (n+1) 时同样成立即可.

    (sum_{i=0}^{n+1}F_i=sum_{i=0}^{n}F_i +F_{n+1}=F_{n+2}-F_1+F_{n+1}=F_{n+3}-F_1)

    即在 (n+1) 处依然成立,证毕.

    PS:当然这个也可以构造一个矩阵同时记录前缀和即可.

    PS:我代码码风改了改...应该可以还算可阅吧...QAQ

    Code

    /**************************************************************
        Problem: 4547
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:324 ms
        Memory:2076 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<iostream>
    using namespace std;
     
    #define debug(a) cout<<#a<<"="<<a<<endl
    typedef long long LL;
    typedef vector<LL> Vec;
    typedef vector<Vec> Mat;
    const LL Mo = 10000007;
    const int N = 100005;
     
    Mat operator * (const Mat &A,const Mat &B){
        Mat C(2,Vec(2));
        for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++)
            C[i][j]=(C[i][j]+A[i][k]*B[k][j])%Mo;
        return C;
    }
    Mat operator ^ (Mat A,LL b){
        Mat res(2,Vec(2));
        res[0][0]=1,res[0][1]=0,res[1][0]=0,res[1][1]=1;
        for(;b;b>>=1,A=A*A){
            if(b&1) res=res*A;
        }return res;
    }
     
    LL n,k;LL a[N];
    inline LL in(LL x=0,char ch=getchar(),int v=1){
        while(ch>'9'||ch<'0') v=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*v;
    }
    int main(){
        n=in(),k=in();
        for(int i=1;i<=n;i++) a[i]=in();
        sort(a+1,a+n+1);
        LL tmp,f0=a[n-1],f1=a[n],ans=0;
        for(int i=1;i<n-1;i++) ans=(ans+a[i]+Mo)%Mo;
        if(f0<0){
            tmp=-f0/f1+1;
            if(tmp<=k){
                k-=tmp,ans=(ans+(f0+f0+f1*(tmp-1))*(tmp)/2%Mo)%Mo;
                f0=(f0+f1*tmp%Mo)%Mo;
                if(f0>f1) swap(f0,f1);
            }
        }
        Mat F(2,Vec(2));F[0][0]=0,F[0][1]=1,F[1][0]=1,F[1][1]=1;
        Mat Fn=F^(k+2);
        ans=(ans+f0*Fn[0][1]%Mo+f1*Fn[1][1]%Mo)%Mo;
        ans=(ans-f1+Mo)%Mo;
        printf("%lld
    ",ans);
        return 0;
    }
    

      

  • 相关阅读:
    python面向编程:阶段练习
    python面向编程:面向对象、init、绑定方法、案例练习
    python常用模块:re模块案例、subprocess
    分享知识-快乐自己:FastDFS 图片服务器的搭建
    分享知识-快乐自己:Nginx概述及如何使用
    分享知识-快乐自己:Java中各种集合特点
    分享知识-快乐自己:虚拟机克隆
    分享知识-快乐自己:安装虚拟机详细步骤
    分享知识-快乐自己:虚拟机 NET 网络配置
    分享知识-快乐自己:IO流基本操作
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/5780695.html
Copyright © 2011-2022 走看看