题目大意:
有一个可重集
S
S
S,一开始大小为
n
n
n,集合中有
n
n
n个数,
a
1
,
a
2
,
.
.
.
,
a
n
−
1
,
a
n
a_1,a_2,...,a_{n-1},a_n
a1,a2,...,an−1,an,小奇每次操作可以加入一个数
a
+
b
a+b
a+b(
a
,
b
∈
S
a,b∈S
a,b∈S),求
k
k
k次操作后它可获得的
S
S
S的和的最大值。
保
证
S
为
非
负
数
保证S为非负数
保证S为非负数
n
<
=
1
0
5
,
k
<
=
1
0
9
,
∣
a
i
∣
<
=
1
0
5
n<=10^5,k<=10^9,|ai|<=10^5
n<=105,k<=109,∣ai∣<=105
分析:
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define MT(x) memset(x, 0, sizeof(x))
#define MP(x, y) memcpy(x, y, sizeof(y))
#define modn 10000007
#define N 100005
using namespace std;
typedef long long ll;
ll D[5][5], C[5][5], A[N], F[5], m;
int n;
void Pre_Work()
{
C[1][1] = 1, C[1][2] = 1, C[1][3] = 0;
C[2][1] = 1, C[2][2] = 0, C[2][3] = 0;
C[3][1] = 1, C[3][2] = 1, C[3][3] = 1;
}
void mul()
{
ll G[5][5]; MT(G);
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
G[i][j] = (G[i][j] + D[i][k] * C[k][j]) % modn;
MP(D, G);
}
void mulself()
{
ll G[5][5]; MT(G);
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
G[i][j] = (G[i][j] + C[i][k] * C[k][j]) % modn;
MP(C, G);
}
int main()
{
Pre_Work();
scanf("%d %lld", &n, &m);
for (int i = 1; i <= n; i++) scanf("%lld", &A[i]), F[3] = (F[3] + A[i]) % modn;
sort(A + 1, A + n + 1);
F[1] = A[n];
F[2] = A[n - 1];
if (F[1] < 0 && F[2] < 0)
{
F[3] = (F[3] + (F[1] + F[2]) * m % modn) % modn;
printf("%lld\n", (F[3] + modn) % modn);
return 0;
}
while (F[2] < 0 && m > 0)
{
F[2] = (F[2] + F[1]) % modn;
F[3] = (F[3] + F[2]) % modn;
--m;
}
if (!m) printf("%lld\n", (F[3] + modn) % modn);
else
{
MP(D, C); --m;
for (; m; m >>= 1)
{
if (m & 1) mul();
mulself();
}
ll G[5]; MT(G);
for (int i = 1; i <= 3; i++)
for (int k = 1; k <= 3; k++)
G[i] = (G[i] + F[k] * D[i][k]) % modn;
printf("%lld\n", (G[3] + modn) % modn);
}
return 0;
}