题目背景

没有背景

我写不出来了qwq

题目描述

Chino给定了nn个数a_1...a_na1​...an​,给定常数s,m,她会轮流对这nn个数做k组操作,每组操作包含以下几步:

1.swap(as​,am​)(交换a_s,a_m​)

2.2将n个数都向前平移一位(第11个移动到第n个位置上)

Chino想知道,k组操作后,这nn个数分别是多少?

Orz yky,dyh,wjk,jjy,cxr,gsy,cpy,zcy,tyz,yy,hz,zhr,yg

输入格式

第一行,四个数,n,s,m,k

接下来一行n个数,分别代表a_1,a_2...a_na1​,a2​...an​

输出格式

输出一行,n个数,分别代表a_1,a_2...a_na1​,a2​...an​

输入输出样例

输入 #1复制

4 1 2 3
1 2 3 4
输出 #1复制

1 2 3 4

说明/提示

所有数字均在long long以内

思路:

  矩阵加速递推,构造两个矩阵,一个存交换操作,一个存位移操作。

  假如交换1和2:

      0 1 0 0

      1 0 0 0

      0 0 0 1

      0 0 0 1

  位移操作,所有往前移一位,

         0 1 0 0

      0 0 1 0

      0 0 0 1

      1 0 0 0    

矩阵快速幂求解K次方,即操作次数:

jz ksm(jz a,int 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;
// a=a*a;当时出错了,因为前面已经计算
}
return anss;
}

重载乘号:

struct jz{
int c[100][100];
}f,base,l1,l2;
int n,m,s,k;
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;
}

 代码:

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#define int long long
using namespace std;
struct jz{
int c[100][100];
}f,base,l1,l2;
int n,m,s,k;
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;
}
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;
}
}
jz ksm(jz a,int 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;
// a=a*a;
}
return anss;
}
signed main()
{
scanf("%lld%lld%lld%lld",&n,&s,&m,&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)l1.c[i][i]=1;
l1.c[s][m]=l1.c[m][s]=1;
for(int i=1;i<=n-1;i++)l2.c[i][i+1]=1;
l2.c[n][1]=1;
base=l1*l2;
base=ksm(base,k);
f=f*base;
for(int i=1;i<=n;i++)printf("%lld ",f.c[i][1]);
cout<<endl;
dy(l1);
cout<<endl;
dy(l2);
return 0;
}

  

感谢wlj_dy 的帮助

05-18 15:34