题目链接:HDU 5171 GTY's birthday gift
题意:每次将序列中两个数相加再加入序列中,反复操作k次,问k次操作后的序列和最大是多少。
思路:序列和最大,显然是每次取序列中最大的两个数相加。
3 2
6 3 2
第一步:6 + 3 = 9
1 * 6 + 1 * 3 = 9
第二步:6 + 3 + 6 = 15
2 * 6 + 1 * 3 = 15
第三步:6 + 3 + 6 + 6 +3 + 6 = 24
3 * 6 + 2 * 3 = 24
第四步:6 + 3 + 6 + 6 +3 + 6 + 6 + 3 + 6 = 39
5 * 6 + 3 * 3 = 39
........
发现每次6和3前面的系数序列是斐波那契序列,加上k很大,想到矩阵快速幂
构造矩阵:
AC代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll __int64
const ll kmod=10000007;
struct Matrix {
ll m[10][10];
};
struct Matrix I,s;
ll n;
ll aa[100010];
bool cmp(int a,int b) {
return a>b;
}
Matrix Mul(Matrix a,Matrix b) {
Matrix c;
ll i,j,k;
for(i=0; i<2; i++) {
for(j=0; j<2; j++) {
c.m[i][j]=0;
for(k=0; k<2; k++) {
c.m[i][j]+=(a.m[i][k]*b.m[k][j]);
c.m[i][j]%=kmod;
}
}
}
return c;
}
Matrix Quickpow(Matrix a,ll n) {
Matrix m,b;
m=a,b=I;
while(n) {
if(n%2)
b=Mul(b,m);
n/=2;
m=Mul(m,m);
}
return b;
}
int main() {
ll i,j;
ll k,a,b,sn,sum;
while(scanf("%I64d %I64d",&n,&k)!=EOF) {
Matrix ans,p,q;
memset(I.m,0,sizeof I.m);
memset(p.m,0,sizeof p.m);
memset(q.m,0,sizeof q.m);
sum=0;
for(i=0; i<n; i++) {
scanf("%I64d",&aa[i]);
sum+=aa[i];
sum%=kmod;
}
sort(aa,aa+n,cmp);
for(i=0; i<2; i++)
I.m[i][i]=1;
q.m[0][0]=2;//f2
q.m[0][1]=1;//f1
q.m[1][0]=0;
q.m[1][1]=0;
p.m[0][0]=1;
p.m[0][1]=1;
p.m[1][0]=1;
p.m[1][1]=0;
if(k==1) {
sn=aa[0]+aa[1]+sum;
} else if(k==2) {
sn=3*aa[0]+2*aa[1]+sum;
} else {
ll tmp;
ans=Quickpow(p,k-2);
ans=Mul(q,ans);
sn=ans.m[0][0]*2+ans.m[0][1]-1-1;
tmp=sn*aa[0];
tmp%=kmod;
ans=Quickpow(p,k-3);
ans=Mul(q,ans);
sn=ans.m[0][0]*2+ans.m[0][1]-1;
tmp+=sn*aa[1]+sum;
}
printf("%I64d\n",tmp%kmod);
}
return 0;
}