description
有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大值。(数据保证这个值为非负数)
analysis
-
正解矩乘
-
考虑 a a a为最大值、 b b b为次大值,那么每次加入的数分别为 a + b , 2 a + b , 3 a + 2 b , 5 a + 3 b . . . a+b,2a+b,3a+2b,5a+3b... a+b,2a+b,3a+2b,5a+3b...
-
所以 a , b a,b a,b的系数分别就是斐波那契数列,稍微有点不同而已
-
又知道 ∑ i = 1 n a [ i ] = a [ i + 2 ] − 1 ( a [ 1 ] = a [ 2 ] = 1 ) \sum_{i=1}^na[i]=a[i+2]-1(a[1]=a[2]=1) ∑i=1na[i]=a[i+2]−1(a[1]=a[2]=1),所以 a , b a,b a,b的系数总和可以直接用矩乘求出来
-
注意次大值可能是负数,就需要不断加上最大值,变成正数后再用上面的方法求解
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define ll long long
#define reg register ll
#define mod 10000007ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))
using namespace std;
ll a[MAXN];
ll n,k,sum;
struct matrix
{
ll m[2][2];
}c;
matrix A={1,1,1,0};
matrix I={1,0,0,1};
O3 inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
O3 inline bool cmp(ll a,ll b)
{
return a>b;
}
O3 inline matrix operator*(matrix a,matrix b)
{
memset(c.m,0,sizeof(c.m));
fo(i,0,1)fo(j,0,1)fo(k,0,1)
(c.m[i][j]+=a.m[i][k]*b.m[k][j]%mod)%=mod;
return c;
}
O3 inline matrix pow(matrix x,ll y)
{
matrix z=I;
while (y){if (y&1)z=z*x;x=x*x,y/=2;}
return z;
}
O3 int main()
{
n=read(),k=read();
fo(i,1,n)a[i]=read(),(sum+=a[i])%=mod;
sort(a+1,a+n+1,cmp);
while (a[1]>0 && a[2]<0)
{
sum+=a[1]+a[2];
a[2]=a[1]+a[2];
k--;
}
printf("%lld\n",(sum+a[1]*(pow(A,k+2).m[0][0]-2)+a[2]*(pow(A,k+1).m[0][0]-1)+mod)%mod);
return 0;
}