当序列中最大和次大都是负数的时候,其相加会是一个更小的负数,因此答案为(Σai)+(m1+m2)*k,如果最大是正数次大是负数,那么一直相加直到两个数都为正数,当最大和次大都是正数时,做一下矩阵乘法即可。
代码
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 200010 5 #define P 10000007 6 using namespace std; 7 typedef long long ll; 8 int n,k,i,j,t1,t2; 9 int a[N]; 10 long long u,v,w,sum; 11 struct g{ 12 long long v[3][3]; 13 void clear() 14 { 15 memset(v,0,sizeof(v)); 16 } 17 }m,o; 18 g operator *(g a,g b) 19 { 20 g c;c.clear(); 21 int i,j,k; 22 for (i=0;i<=2;i++) 23 for (j=0;j<=2;j++) 24 for (k=0;k<=2;k++) 25 c.v[i][j]=(c.v[i][j]+a.v[i][k]*b.v[k][j])%P; 26 return c; 27 } 28 g ksm(int x) 29 { 30 g ans; 31 if (x==1) 32 return o; 33 ans=ksm(x/2); 34 ans=ans*ans; 35 if (x%2) 36 ans=ans*o; 37 return ans; 38 } 39 int main() 40 { 41 a[0]=-2000000000; 42 scanf("%d%d",&n,&k); 43 for(i=1;i<=n;i++) 44 { 45 scanf("%d",&a[i]); 46 sum=(sum+a[i])%P; 47 if (a[i]>a[t1]) t1=i; 48 } 49 for (i=1;i<=n;i++) 50 if ((i!=t1)&&(a[i]>a[t2])) t2=i; 51 u=a[t1];v=a[t2]; 52 if ((u<=0)&&(v<=0)) 53 { 54 sum=(sum+(u+v)*k)%P; 55 } 56 else 57 { 58 while (((u<=0)||(v<=0))&&(k)) 59 { 60 w=u+v;sum=(w+sum)%P; 61 u=max(u,v);v=w;k--; 62 } 63 if (u>v) 64 { 65 w=v;v=u;u=w; 66 } 67 o.clear(); 68 o.v[0][1]=o.v[1][0]=o.v[1][1]=1; 69 o.v[2][0]=o.v[2][1]=o.v[2][2]=1; 70 if (k) m=ksm(k); 71 /* 72 for (i=0;i<=2;i++) 73 { 74 for (j=0;j<=2;j++) 75 printf("%d ",m.v[i][j]); 76 printf(" "); 77 } 78 */ 79 sum=(sum+u*m.v[2][0]+v*m.v[2][1])%P; 80 } 81 printf("%lld ",sum); 82 } 83 /* 84 0 1 0 85 1 1 0 86 1 1 1 87 */