一个序列a,k次操作,每次把其中两个数的和相加后得到的新数添加到序列中,问最后得到的序列的和的最大值。
设最大的两个数为a[n],a[n-1],所有数的和为s[n],可得转移矩阵:(a[n],a[n-1],s[n])=(a[n-1],a[n-2],s[n-1])*(1 1 1)
(1 0 1)
(0 0 1)
设最初最大的两个数为a1,a2,所有数之和为s2,则(a[k+2],a[k+1],s[k+2])=(a2,a1,s2)*(1 1 1)^k
(1 0 1)
(0 0 1)
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define LL __int64 #define maxn 4 #define MOD 10000007 struct Matrix { LL a[maxn][maxn]; Matrix() { memset(a,0,sizeof(a)); for(int i=1;i<maxn;++i) a[i][i]=1; } }; Matrix operator *(Matrix A,Matrix B) { Matrix C; for(int i=1;i<maxn;++i) for(int j=1;j<maxn;++j) { C.a[i][j]=0; for(int k=1;k<maxn;++k) C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%MOD)%MOD; } return C; } LL s; Matrix pow(Matrix A,int n) { Matrix res; while(n) { if(n&1) res=res*A; A=A*A; n>>=1; } return res; } LL a[100005]; int main() { int n,k; while(scanf("%d%d",&n,&k)!=EOF) { s=0; for(int i=1;i<=n;++i) { scanf("%I64d",&a[i]); s=(s+a[i])%MOD; } sort(a+1,a+1+n); Matrix A; A.a[1][1]=1,A.a[1][2]=1,A.a[1][3]=1; A.a[2][1]=1,A.a[2][2]=0,A.a[2][3]=1; A.a[3][1]=0,A.a[3][2]=0,A.a[3][3]=1; A=pow(A,k); s=A.a[3][3]*s%MOD; s=(s+A.a[1][3]*a[n]%MOD)%MOD; s=(s+A.a[2][3]*a[n-1]%MOD)%MOD; printf("%I64d\n",s); } return 0; }