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取模。
Sample Input
2 2
3 6
Sample Output
33
题解
把数集从小到大排序,简单思考一下肯定是每次加入a[n]+a[n-1]最优。
然后稍微推一下可以发现,a[n]与a[n-1]对于k来说,前面的系数都是斐波那契数列里的数
写个矩乘
还没完,假如a[n]>0,a[n-1]<0怎么办,那么每次加入a[n]+a[n-1]就不是最优了
我们暴力出a[n]*k+a[n-1]>=0中k的最小值,代表每次都加入这个。由于abs(a[n])<=10^5,这个暴力最大的复杂度是10^5了
暴力完之后,再用暴力出来的数与a[n]作为新数加入数列中。
由于这题保证答案大于0所以不需要考虑a[n]<0的情况,虽然我考虑了
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=10000007;
struct matrix
{
LL m[5][5];
matrix(){memset(m,0,sizeof(m));}
}st,tmp,stx,sty;
matrix multi(matrix u,matrix v,int n,int m,int p)
{
matrix ret;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=p;k++)
ret.m[i][k]=(ret.m[i][k]+u.m[i][j]*v.m[j][k])%mod;
return ret;
}
matrix pow_mod(matrix u,int b)
{
matrix ans;
for(int i=1;i<=4;i++)ans.m[i][i]=1;
while(b)
{
if(b%2==1)ans=multi(ans,u,4,4,4);
u=multi(u,u,4,4,4);b/=2;
}
return ans;
}
int pow_(int a,int b)
{
int ans=1;
while(b)
{
if(b%2==1)ans=(ans*a)%mod;
a=(a*a)%mod;b/=2;
}
return ans;
}
int n,k;LL a[110000],sum;
bool check(int kk)
{
sum=a[n-1];
sum+=a[n]*kk;
if(sum>=0)return true;
return false;
}
int main()
{
scanf("%d%d",&n,&k);
int bk=0;
for(int i=1;i<=n;i++){scanf("%lld",&a[i]);if(a[i]>0)bk++;}
sort(a+1,a+1+n);
if(bk==0)
{
LL ans=0;
for(int i=1;i<=n;i++)ans=(ans+a[i])%mod;
ans=(ans+pow_(a[n-1],k))%mod;ans=(ans+pow_(a[n],k))%mod;
printf("%lld\n",ans);
}
else
{
if(k==0)
{
LL ans=0;
for(int i=1;i<=n;i++)ans=(ans+a[i])%mod;
printf("%lld\n",ans);
return 0;
}
if(bk>=2)
{
st.m[1][2]=st.m[2][1]=st.m[2][2]=st.m[3][4]=st.m[4][2]=st.m[4][4]=1;
tmp.m[1][1]=1*a[n-1];tmp.m[2][1]=1*a[n-1];tmp.m[3][1]=0;tmp.m[4][1]=1*a[n-1];
matrix p=multi(pow_mod(st,k-1),tmp,4,4,1);
tmp.m[1][1]=1*a[n];tmp.m[2][1]=2*a[n];tmp.m[3][1]=0;tmp.m[4][1]=1*a[n];
matrix q=multi(pow_mod(st,k-1),tmp,4,4,1);
LL ans=0;
for(int i=1;i<=n;i++)ans=(ans+a[i])%mod;
ans=(ans+q.m[4][1])%mod;ans=(ans+p.m[4][1])%mod;
printf("%lld\n",ans);
}
if(bk==1)
{
LL ans=0;
for(int i=1;i<=n;i++)ans=(ans+a[i])%mod;
int kk=1,kt=a[n-1]+a[n];ans+=kt;
while(kt<0){kt+=a[n];ans+=kt;kk++;}
a[n-1]=min((LL)kt,a[n]);a[n]=max((LL)kt,a[n]);
st.m[1][2]=st.m[2][1]=st.m[2][2]=st.m[3][4]=st.m[4][2]=st.m[4][4]=1;
tmp.m[1][1]=1*a[n-1];tmp.m[2][1]=1*a[n-1];tmp.m[3][1]=0;tmp.m[4][1]=1*a[n-1];
matrix p=multi(pow_mod(st,k-kk-1),tmp,4,4,1);
tmp.m[1][1]=1*a[n];tmp.m[2][1]=2*a[n];tmp.m[3][1]=0;tmp.m[4][1]=1*a[n];
matrix q=multi(pow_mod(st,k-kk-1),tmp,4,4,1);
ans=(ans+q.m[4][1])%mod;ans=(ans+p.m[4][1])%mod;
printf("%lld\n",ans);
}
}
return 0;
}