题目:
题解:
数据范围和转移的相同性让我们很容易判断出来是个矩阵乘法
设计也很简单|sum max1 max2|*系数矩阵
写的时候有一个细节问题,就是当max1=1,max2=-1的时候,按照我们的转移,转移一步之后的结果是max1=0,max2=1,显然不符合大小关系了,事实上只要最大值最小值是一正一副就会出现这种情况,那么我们要处理一下,处理的过程中不要忘记这个时候的sum&k也是变化的
代码:
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
#define INF 1e9
const int mod=10000007;
struct mat
{
LL sq[5][5];
void clear(){memset(sq,0,sizeof(sq));}
}ans,mul;
mat cf(mat a,mat b,int id)
{
mat c;c.clear();
for (int i=1;i<=id;i++)
for (int j=1;j<=3;j++)
for (int k=1;k<=3;k++)
c.sq[i][j]=(c.sq[i][j]+a.sq[i][k]*b.sq[k][j]%mod)%mod;
return c;
}
mat ksm(mat a,LL k)
{
mat ans=a;k--;
for (;k;k>>=1,a=cf(a,a,3))
if (k&1) ans=cf(ans,a,3);
return ans;
}
int main()
{
int n,k;scanf("%d%d",&n,&k);
LL max1=-INF,max2=-INF,x;
for (int i=1;i<=n;i++)
{
scanf("%lld",&x);
if (x>max1) max2=max1,max1=x;
else if (x>max2) max2=x;
ans.sq[1][1]=(x+ans.sq[1][1])%mod;
}
while (max2<0 && k) k--,max2+=max1,ans.sq[1][1]=(max2+ans.sq[1][1])%mod;
ans.sq[1][2]=max1; ans.sq[1][3]=max2;
mul.sq[1][1]=1;mul.sq[2][1]=1;mul.sq[3][1]=1;mul.sq[2][2]=1;
mul.sq[3][2]=1;mul.sq[2][3]=1;
mul=ksm(mul,k);ans=cf(ans,mul,1);
printf("%lld",ans.sq[1][1]);
}