题目链接: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; }
HDU 5171 GTY's birthday gift (矩阵快速幂)
原文地址:http://blog.csdn.net/u012377575/article/details/43611699