Matrix accelerated recurrence
N range is relatively small, a large range of k, we can consider starting from n.
1. First, we know that any matrix * matrix will not change.
So for the exchange operation, we can create such a matrix:
Addition of s, m rows, every other row is f [i] [i] = 1;
S-line: f [s] [m] = 1; m-th row: f [m] [s] = 1;
Then we completed the exchange operation.
2. For the left shift operation, we can create such a matrix:
In addition to n-th row, every other row is f [i] [i + 1] = 1;
N-th row: f [n] [1] = 1;
3. Our initial matrix f [i] [1] = a [i];
Because the binding matrix in line with the law, so we can speed up a similar rapid power method.
Then it can be, the time complexity O ( \ (n-^. 3 \ Times log (K) \) ).
I offer long and stinking code
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long n,s,m,k;
struct jz
{
long long c[85][85];
}f,base,lin1,lin2;
jz operator * (const jz &a,const jz &b)//矩阵重载乘号
{
jz lin;
for(int i=1;i<=80;++i)
{
for(int j=1;j<=80;++j)
{
lin.c[i][j]=0;
for(int k=1;k<=80;++k)
{
lin.c[i][j]+=(a.c[k][j]*b.c[i][k]);
}
}
}
return lin;
}
jz ksm(jz a,long long b)
{
jz anss;
memset(anss.c,0,sizeof(anss.c));
for(int i=1;i<=n;++i)anss.c[i][i]=1;
for(;b;b>>=1,a=a*a)
{
if(b&1)
anss=a*anss;
}
return anss;
}
void dy(jz x)//调试用的,可以忽略
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
cout<<x.c[i][j]<<" ";
cout<<endl;
}
}
int main()
{
cin>>n>>m>>s>>k;
for(int i=1;i<=n;++i)scanf("%lld",&f.c[i][1]);
for(int i=1;i<=n;++i)if(i!=s&&i!=m)lin1.c[i][i]=1;
lin1.c[s][m]=lin1.c[m][s]=1;
for(int i=1;i<=n-1;++i)lin2.c[i][i+1]=1;
lin2.c[n][1]=1;
base=lin1*lin2;
base=ksm(base,k);
f=f*base;
for(int i=1;i<=n;++i)printf("%lld ",f.c[i][1]);
return 0;
}