Description
有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大值。(数据保证这个值为非负数)
Solution
很显然,我们每次肯定是取集合中最大的两个数,那么我们设这两个数为
a
,
但是题目有负数,也就是说
a
可能小于
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define mo 10000007
#define ll long long
#define N 100010
using namespace std;
int a[N];
ll r[4],z[4];
ll zy[4][4]={
{0},
{0,0,1,1},
{0,1,1,1},
{0,0,0,1}
};
ll c[4][4],b[4][4];
void mul(ll p[4][4],ll q[4][4])
{
memset(c,0,sizeof(c));
fo(i,1,3)
fo(j,1,3)
fo(k,1,3) c[i][j]=(c[i][j]+p[i][k]*q[k][j]%mo)%mo;
memcpy(p,c,sizeof(c));
}
void pow(int t)
{
fo(i,1,3) b[i][i]=1;
while(t)
{
if(t%2) mul(b,zy);
t/=2;
mul(zy,zy);
}
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
ll s=0;
fo(i,1,n) scanf("%d",&a[i]),s+=a[i];
sort(a+1,a+n+1);
r[2]=a[n];
r[1]=a[n-1];
if(r[1]<0 && m) r[1]=a[n]+a[n-1],r[2]=a[n],r[3]+=r[1],m--;
pow(m);
fo(j,1,3)
fo(k,1,3) z[j]=(z[j]+r[k]*b[k][j]%mo)%mo;
printf("%lld",(z[3]+s%mo+mo)%mo);
}