这道题存在地推关系,首先贪心的想,要想每次使和增长最快,一定是选取两个最大的,那么新的数又一定成为最大,之前的最大变为次大,递推关系很明显,那么我们设和为sum (最大的不算在内) , 最大的设为a ,次大的设为b
矩阵如下:
[sum , a, b]
变换矩阵如下:
100
111
010
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MOD 10000007
#define MAX 5
#define size 3
using namespace std;
typedef long long LL;
LL n,m;
LL sum , a , b, c;
struct mat
{
LL a[MAX][MAX];
mat ( )
{
memset ( a , 0 , sizeof ( a ) );
}
};
void set ( mat& m )
{
for ( int i = 1 ; i <= size ; i++ ) m.a[i][i] = 1;
}
mat multi ( const mat& m1 , const mat& m2 )
{
mat ret;
for ( int i = 1 ; i <= size ; i++ )
for ( int j = 1 ; j <= size ; j++ )
if ( m1.a[i][j] )
for ( int k = 1 ; k <= size ; k++ )
ret.a[i][k] = ( ret.a[i][k] + ( m1.a[i][j]*m2.a[j][k] )%MOD )%MOD;
return ret;
}
mat quickMulti ( mat m , LL n )
{
mat ret;
set ( ret );
while ( n )
{
if ( n&1 ) ret = multi ( ret , m );
m = multi ( m , m );
n>>= 1;
}
return ret;
}
int main ( )
{
while ( ~scanf ( "%lld%lld" , &n , &m ) )
{
sum = 0 , a = 0 , b = 0;
for ( int i = 0 ; i < n ; i++ )
{
scanf ( "%lld" , &c );
if ( c > a )
{
b = a;
a = c;
}
else if ( c > b ) b = c;
sum += c;
sum %= MOD;
}
sum -= a;
mat ans,vary;
ans.a[1][2] = a , ans.a[1][3] = b , ans.a[1][1] = sum;
vary.a[1][1] = vary.a[2][1] = vary.a[2][2] = vary.a[2][3] = vary.a[3][2] = 1;
vary = quickMulti ( vary , m+1 );
ans = multi ( ans , vary );
printf ( "%lld\n" , ans .a[1][1] );
}
}