AGC044C Strange Dance
Description
There are $3^N$ people dancing in circle. We denote with $0,1,\cdots ,3^N-1$ the positions in the circle, starting from an arbitrary position and going around clockwise. Initially each position in the circle is occupied by one person.
The people are going to dance on two kinds of songs: salsa and rumba.
- When a salsa is played, the person in position $i$ goes to position $j$, where $j$ is the number obtained replacing all digits $1$ with $2$ and all digits $2$ with $1$ when reading $i$ in base $3$ (e.g., the person in position $46$ goes to position $65$).
- When a rumba is played, the person in position $i$ moves to position $i+1$ (with the identification $3N=0$).
You are given a string $T=T_1T_2 \cdots T_{|T|}$ such that $T_i=S$ if the ii-th song is a salsa and $T_i=R$ if it is a rumba. After all the songs have been played, the person that initially was in position $i$ is in position $P_i$. Compute the array $P_0,P_1,\dots, P_{3^N-1}$
Solution
维护一个Trie,每个点延伸三条边表示下一个数位上是0/1/2,表示时从低位到高位
1/2翻转的操作可以打标记
+1取模的操作可以交换Trie的三个子节点,并在0节点下递归进行(考虑进位)
最后对于每个叶子的权值,到达的位置就是由根到它路径上的数组成的数
#include<iostream> #include<utility> #include<vector> #include<cstdio> using namespace std; int n=1,N,base[20]={1},cnt=1,tr[2000005][3],val[2000005],tag[2000005],ans[600005]; char str[200005]; inline int read() { int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } void build(int now,int dep,int v) { if(dep==N+1) { val[now]=v;return; } for(int i=0;i<=2;i++) tr[now][i]=++cnt,build(cnt,dep+1,v+base[dep-1]*i); } void update(int now) { if(tag[now]) swap(tr[now][1],tr[now][2]),tag[tr[now][0]]^=1,tag[tr[now][1]]^=1,tag[tr[now][2]]^=1,tag[now]=0; int temp=tr[now][0]; tr[now][0]=tr[now][2],tr[now][2]=tr[now][1],tr[now][1]=temp; if(tr[now][0]) update(tr[now][0]); } void dfs(int now,int ret,int dep) { if(!tr[now][0]) { ans[val[now]]=ret;return; } if(tag[now]) swap(tr[now][1],tr[now][2]),tag[tr[now][0]]^=1,tag[tr[now][1]]^=1,tag[tr[now][2]]^=1,tag[now]=0; for(int i=0;i<=2;i++) dfs(tr[now][i],ret+base[dep]*i,dep+1); } int main() { N=read(); for(int i=1;i<=N;i++) n*=3; for(int i=1;i<=N;i++) base[i]=base[i-1]*3; build(1,1,0); scanf("%s",str); for(int i=0;str[i];i++) { if(str[i]=='S') tag[1]^=1; else update(1); } dfs(1,0,0); for(int i=0;i<n;i++) printf("%d ",ans[i]); return 0; }