簡要題意:
漢諾塔,三個盤子成環,只允許將盤子挪到順時針下一個,問把 柱上的所有盤子全部挪到 柱上至少需要幾次操作,挪到 又要幾次操作。
設 表示把 個盤子全部挪到順時針下一個位置的操作次數 , 同理,不過是挪到下下個位置。
手玩可以發現遞推式:
由於變化是線性的,矩陣快速冪轉移即可。
由於詢問次數有點爆炸,BSGS預處理即可。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}
inline ll gl(){return get_integer<ll>();}
}using namespace IO;
using std::cerr;
using std::cout;
cs int mod=998244353;
struct mat{
int a[3][3];mat(){memset(a,0,sizeof a);}
int* operator[](int o){return a[o];}
cs int* operator[](int o)cs{return a[o];}
};
mat operator*(cs mat &A,cs mat &B){
mat C;
C[0][0]=((ll)A[0][0]*B[0][0]+(ll)A[0][1]*B[1][0]+(ll)A[0][2]*B[2][0])%mod;
C[0][1]=((ll)A[0][0]*B[0][1]+(ll)A[0][1]*B[1][1]+(ll)A[0][2]*B[2][1])%mod;
C[0][2]=((ll)A[0][0]*B[0][2]+(ll)A[0][1]*B[1][2]+(ll)A[0][2]*B[2][2])%mod;
C[1][0]=((ll)A[1][0]*B[0][0]+(ll)A[1][1]*B[1][0]+(ll)A[1][2]*B[2][0])%mod;
C[1][1]=((ll)A[1][0]*B[0][1]+(ll)A[1][1]*B[1][1]+(ll)A[1][2]*B[2][1])%mod;
C[1][2]=((ll)A[1][0]*B[0][2]+(ll)A[1][1]*B[1][2]+(ll)A[1][2]*B[2][2])%mod;
C[2][0]=((ll)A[2][0]*B[0][0]+(ll)A[2][1]*B[1][0]+(ll)A[2][2]*B[2][0])%mod;
C[2][1]=((ll)A[2][0]*B[0][1]+(ll)A[2][1]*B[1][1]+(ll)A[2][2]*B[2][1])%mod;
C[2][2]=((ll)A[2][0]*B[0][2]+(ll)A[2][1]*B[1][2]+(ll)A[2][2]*B[2][2])%mod;
return C;
}
mat A;
cs int K=1<<10|7;
mat pw0[K],pw1[K],pw2[K],pw3[K];
void Main(){
A[0][0]=1,A[0][1]=2,A[0][2]=1;
pw0[1][0][0]=0,pw0[1][0][1]=1,pw0[1][0][2]=0;
pw0[1][1][0]=2,pw0[1][1][1]=2,pw0[1][1][2]=0;
pw0[1][2][0]=1,pw0[1][2][1]=2,pw0[1][2][2]=1;
pw0[0][0][0]=pw0[0][1][1]=pw0[0][2][2]=1;
pw1[0]=pw2[0]=pw3[0]=pw0[0];
for(int re i=2;i<=(1<<10);++i)pw0[i]=pw0[i-1]*pw0[1];
pw1[1]=pw0[1<<10];
for(int re i=2;i<=(1<<10);++i)pw1[i]=pw1[i-1]*pw1[1];
pw2[1]=pw1[1<<10];
for(int re i=2;i<=(1<<10);++i)pw2[i]=pw2[i-1]*pw2[1];
pw3[1]=pw2[1<<10];
for(int re i=2;i<=(1<<10);++i)pw3[i]=pw3[i-1]*pw3[1];
int T=gi(),a=0,b=0;
while(T--){ll n=gl()-1;
mat res=A*(pw0[n&1023]*pw1[n>>10&1023])*(pw2[n>>20&1023]*pw3[n>>30&1023]);
a^=res[0][0],b^=res[0][1];
}cout<<a<<" "<<b<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("riemannian.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
freopen("riemannian.in","r",stdin);
freopen("riemannian.out","w",stdout);
#endif
#endif
}
signed main(){file();Main();return 0;}