CF385E Bear in the Field
呜呜呜,调了我一下午的矩阵快速幂。(;′⌒`)
Solution
首先,我们将题目的意思模拟一下,可以得到:
\[dx_i=dx_{i-1}+sx_{i-1}+sy_{i-1}+i-1,\\dy_i=dy_{i-1}+sx_{i-1}+sy_{i-1}+i-1,\\sx_i=sx_{i-1}+dx_i,sy_i=sy_{i-1}+dy_i
\]
但是因为要 \(\%n\) ,所以坐标从 \(1\sim n\) 到了 \(0\sim n-1\) ,那么我们的速度此时会少2,因此再加上一个2。
于是就有:
\[dx_i=dx_{i-1}+sx_{i-1}+sy_{i-1}+(i-1)+2\\dy_i=dy_{i-1}+sx_{i-1}+sy_{i-1}+(i-1)+2\\sx_i=sx_{i-1}+dx_i=2\times sx_{i-1}+dx_{i-1}+sy_{i-1}+(i-1)+2,\\sy_i=sy_{i-1}+dy_i=2\times sy_{i-1}+dy_{i-1}+sx_{i-1}+(i-1)+2
\]
下一步,我发现 \(0\le t\le 10^{18}\) ,于是想到了矩阵快速幂,发现的确 \(sx,sy,dx,dy,i\) 都和上一步有关系,那么转移矩阵就出来了:
\[\begin{bmatrix}2~~~1~~~1~~~0~~~1~~~2\\1~~~2~~~0~~~1~~~1~~~2\\1~~~1~~~1~~~0~~~1~~~2\\1~~~1~~~0~~~1~~~1~~~2\\0~~~0~~~0~~~0~~~1~~~1\\0~~~0~~~0~~~0~~~0~~~1\end{bmatrix}
\]
初始矩阵也有:
\[\begin{bmatrix}sx_0\\sy_0\\dx_0\\dy_0\\0\\1\end{bmatrix}
\]
然后就是:
\[\begin{bmatrix}sx_n\\sy_n\\dx_n\\dy_n\\t\\1\end{bmatrix}=\begin{bmatrix}2~~~1~~~1~~~0~~~1~~~2\\1~~~2~~~0~~~1~~~1~~~2\\1~~~1~~~1~~~0~~~1~~~2\\1~~~1~~~0~~~1~~~1~~~2\\0~~~0~~~0~~~0~~~1~~~1\\0~~~0~~~0~~~0~~~0~~~1\end{bmatrix}^t\begin{bmatrix}sx\\sy\\dx\\dy\\0\\1\end{bmatrix}
\]
其实最后只需要 \(sx_n,sy_n\) ,所以转移完只需要单独算一下前两个就行了。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=15;
int n,sx,sy,dx,dy,t,mod,y[N];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
inline int add(int a,int b){return a+b<mod?a+b:a+b-mod;}
inline int sub(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline fpow(int a,int b){
int res=1;
while(b){
if(b&1) res=mul(res,a);
a=mul(a,a);
b>>=1;
}
return res;
}
struct matrix{
int a[N][N];
matrix(){memset(a,0,sizeof(a));}
matrix operator * (const matrix &x) const {
matrix ans;
for(int i=1;i<=6;i++)
for(int j=1;j<=6;j++)
for(int k=1;k<=6;k++)
ans.a[i][j]=add(ans.a[i][j],mul(a[i][k],x.a[k][j]));
return ans;
}
}I;
matrix Fpow(matrix a,int b){
matrix res;
for(int i=1;i<=6;i++) res.a[i][i]=1;
while(b){
if(b&1) res=res*a;
a=a*a;
b>>=1;
}
return res;
}
inline void init(){
y[1]=sx-1,y[2]=sy-1,y[3]=dx,y[4]=dy,y[5]=0,y[6]=1;
I.a[1][1]=I.a[2][2]=I.a[1][6]=I.a[2][6]=I.a[3][6]=I.a[4][6]=2;
I.a[1][2]=I.a[1][3]=I.a[1][5]=I.a[2][1]=I.a[2][4]=I.a[2][5]=I.a[3][1]=I.a[3][2]=I.a[3][3]=
I.a[3][5]=I.a[4][1]=I.a[4][2]=I.a[4][4]=I.a[4][5]=I.a[5][5]=I.a[5][6]=I.a[6][6]=1;
}
signed main(){
scanf("%lld%lld%lld%lld%lld%lld",&n,&sx,&sy,&dx,&dy,&t);
if(t==0){
printf("%lld %lld",sx,sy);
return 0;
}
mod=n;
init();
I=Fpow(I,t);
int ex=0,ey=0;
for(int i=1;i<=6;i++)
ex=((ex+I.a[1][i]*y[i])%mod+mod)%mod;
for(int i=1;i<=6;i++)
ey=((ey+I.a[2][i]*y[i])%mod+mod)%mod;
printf("%lld %lld",ex+1,ey+1);
return 0;
}