给n个数,k次操作,每次操作取两个数加入集合,问最后的集合所有数的和(%MOD)最大, 解法:要使得结果最大,最优的办法就是每次取最大的两个数,加入集合,递推几个,便可以发现结果只与最大两个数的个数有关。 加入的数:第一次:max1+max2 sum多加入的数max1+max2 第二次:2*max1+max2 sum多加入的数3*max1+2*max2 第三次:3*max1+2*max2 sum多加入的数6*max1+4*max2 第四次:5*max1+3*max2 sum多加入的数11*max1+7*max2 第五次:8*max1+5*max2 sum多加入的数19*max1+12*max2
所以: f1=1,f2=2 多加入的数max1为有递推式 fn+1=fn+fn−1+2 /max2的n+1项-1; 多加入的数max2为有递推式 fn=fn−1+fn−2+1 直接对max2构造矩类似于斐波拉契数列的阵快速幂的矩阵,优化运算 #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> using namespace std; #define LL long long #define MOD 10000007 struct Mat{ int n,m; LL mat[9][9]; }; Mat operator *(Mat a,Mat b){ Mat c; memset(c.mat,0,sizeof(c.mat)); c.n = a.n,c.m = b.m; for(int i=1;i<=a.n;i++){ for(int j=1;j<=b.m;j++){ for(int k=1;k<=a.m;k++){ c.mat[i][j] += (a.mat[i][k]*b.mat[k][j])%MOD; c.mat[i][j] %= MOD; } } } return c; } Mat operator +(Mat a,Mat b){ Mat c; memset(c.mat,0,sizeof(c.mat)); c.n = a.n,c.m = a.m; for(int i=1;i<=a.n;i++){ for(int j=1;j<=a.m;j++){ c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD; } } return c; } Mat operator ^(Mat a,int k){ Mat c; memset(c.mat,0,sizeof(c.mat)); c.n = a.n,c.m = a.n; for(int i=1;i<=a.n;i++)c.mat[i][i] = 1; while(k){ if(k&1){ c = c*a; } a = a*a; k>>=1; } return c; } void out(Mat a){ for(int i=1;i<=a.n;i++){ for(int j=1;j<=a.m;j++){ printf(j==a.m? "%I64d\n":"%I64d ",a.mat[i][j]); } } } int main(){ int n,k; while(scanf("%d %d",&n,&k)!=EOF){ int x; LL ans=0; int max1=0,max2=0; while(n--){ scanf("%d",&x); ans+=x; if(x> max2)max2=x; if(max1<max2) swap(max1,max2); } if(k==1){ ans+=(max1+max2); ans%=MOD; } else if(k==2){ ans+=(3*max1+2*max2); ans%=MOD; } else{ Mat d; d.n=3,d.m=3; d.mat[1][1]=1,d.mat[1][2]=1,d.mat[1][3]=0; d.mat[2][1]=1,d.mat[2][2]=0,d.mat[2][3]=0; d.mat[3][1]=1,d.mat[3][2]=0,d.mat[3][3]=1; Mat temp=d^(k-2); //cout<<2*temp.mat[1][1]+temp.mat[2][1]+temp.mat[3][1]<<endl; ans+=(2*temp.mat[1][1]+temp.mat[2][1]+temp.mat[3][1])*max2%MOD; temp=temp*d; ans%=MOD; //cout<<2*temp.mat[1][1]+temp.mat[2][1]+temp.mat[3][1]-1<<endl; ans+=(2*temp.mat[1][1]+temp.mat[2][1]+temp.mat[3][1]-1)*max1%MOD; ans%=MOD; } printf("%I64d\n",ans); } return 0; }