3 2 3 6 2
35
显然每次会从可重集中选择最大的两个进行操作,设这两数为a,b(a>=b) ,操作之后的数一定是操作后集合中最大的,下一次选取的数一定是a+b 和a ,这就形成了一个类似于斐波那契数列的东西,矩阵乘法快速幂求前n项和即可,转移矩阵如下
1 0 1 sum
0 1 1 * a+b
0 1 0 a
设矩阵A为
1 0 1
0 1 1
0 1 0
B为
sum
a+b
a
ans=A^k*B,接着矩阵快速幂
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int mod=10000007; typedef struct matrix { long long ma[5][5]; }matrix; matrix multi(matrix x,matrix y) { matrix ans; memset(ans.ma,0,sizeof(ans.ma)); for(int i=1;i<=3;i++) { for(int j=1;j<=3;j++) { if(x.ma[i][j]) for(int k=1;k<=3;k++) { ans.ma[i][k]=(ans.ma[i][k]+(x.ma[i][j]*y.ma[j][k])%mod)%mod; } } } return ans; } int main() { long long sum; long long n,k; while(~scanf("%I64d%I64d",&n,&k)) { sum=0; long long t, maxf=0,maxs=0; for(int i=0;i<n;i++) { scanf("%I64d",&t); sum=(sum+t)%mod; if(t>maxf) { maxs=maxf; maxf=t; } else if(t>maxs) maxs=t; } matrix a,b,ans; memset(ans.ma,0,sizeof(ans.ma)); for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) if(i==j) ans.ma[i][j]=1; memset(a.ma,0,sizeof(a.ma)); a.ma[1][1]=a.ma[1][2]=a.ma[2][2]=a.ma[2][3]=a.ma[3][2]=1; while(k) { if(k&1) ans=multi(a,ans); a=multi(a,a); k=k>>1; } memset(b.ma,0,sizeof(b.ma)); b.ma[1][1]=sum; b.ma[2][1]=maxf+maxs; b.ma[3][1]=maxf; ans=multi(ans,b); printf("%I64d\n",ans.ma[1][1]); } return 0; }
??
hdu 5171 GTY's birthday gift (BestCoder Round #29)
原文地址:http://blog.csdn.net/caduca/article/details/43614569