题目:http://acm.hdu.edu.cn/showproblem.php?pid=5171
题意:
给你N个数字,让你用这些数字构造一个最大的集合,其中可以选取M次最大的俩个数加入集合中,求最后集合中的数最大。
Multi test cases (about 3) . The first line contains two integers n and k (2≤n≤100000,1≤k≤1000000000). The second line contains n elements ai (1≤ai≤100000)separated by spaces , indicating the multiset S .
分析:
k的值辣么大,肯定是快速幂啊!然后就想推个公式,去求解。
显然要保证加入的数最大,必须要让集合中最大的两个相加,设为a,b;然后现在集合中有了一个更大的数c,所以再往集合中加数的时候,要加c,a,现在最大的数是d,再加就是d,c…….规律就是f[n]=f[n-1]+f[n-2],这不就是fib吗!然后化成矩阵的形式,就好了、
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=10000007;
struct Mat{
ll mat[3][3];
};
Mat mul(Mat a,Mat b)
{
Mat c; memset(c.mat,0,sizeof(c.mat));
for(int k=0;k<3;k++)
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%mod;
return c;
}
Mat qmod(Mat a,ll k)
{
Mat c;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
c.mat[i][j]=(i==j);
for(;k;k>>=1){
if(k&1)c=mul(a,c);
a=mul(a,a);
}
return c;
}
int a[100002];
int main()
{
int n;ll k;
while(~scanf("%d%I64d",&n,&k)){
ll sum=0;
for(int i=0;i<n;i++)scanf("%d",&a[i]),sum+=a[i];
sort(a,a+n);
Mat c;
c.mat[0][0]=c.mat[0][1]=c.mat[0][2]=1;
c.mat[1][0]=0;c.mat[1][1]=c.mat[1][2]=1;
c.mat[2][0]=0;c.mat[2][1]=1;c.mat[2][2]=0;
Mat ans=qmod(c,k);
int res=(ans.mat[0][0]*sum+ans.mat[0][1]*a[n-1]+ans.mat[0][2]*a[n-2])%mod;
printf("%d
",res);
}
return 0;
}