zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    malloc函数具体解释
    GeeksforGeeks
    debugging python with IDLE
    sqlplus登录问题
    SNMP协议具体解释
    MP4文件格式具体解释——结构概述
    【C++模版之旅】项目中一次活用C++模板(traits)的经历
    简单的REST的框架实现
    23种设计模式(3):抽象工厂模式
    给字符数组赋值的方法
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676232.html
Copyright © 2011-2022 走看看