1. 程式人生 > 其它 >agc044c&10.13 T2

agc044c&10.13 T2

題意:給定\(3^n\)個數\([0,3^n-1)\),給出兩種操作,

 1.每個數在三進位制下互換1,2
 2.每個數加一對三的n次方取模。

求最終序列。

\(n\leq 12,m\leq 2\times 10^5\)

sol

考慮把序列丟到一棵\(012trie\)上,對於操作\(1\),我們直接給根節點打一個標記。

對於\(2\)操作,我們直接在\(Trie\)樹上模擬即可,具體的,我們把當前節點的\(0\)兒子當做新的\(1\)兒子,把\(1\)兒子當做新的\(2\)兒子,\(2\)兒子當做新的\(0\)兒子,然後從目前的\(0\)兒子繼續遞迴。

上述操作即為進位,總複雜度為\(O(3^n+|S|\times n)\)

#include <bits/stdc++.h>
using namespace std;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
    return x*f;
}
#define M 8000005
#define N 15
#define KK 200005
int trie[M][3],ls[M];
int n;
int num,cnt=1;
#define ch0 trie[x][0]
#define ch1 trie[x][1]
#define ch2 trie[x][2]
inline void ins(int x){
	int p=1;
	for(int i=1;i<=n;i++){
		int cc=x%3;x/=3;
		if(!trie[p][cc])trie[p][cc]=++cnt;
		p=trie[p][cc];
	}
	ls[p]=++num;
}
int v[M];
inline void pushdown(int x){
	if(v[x]){
		v[x]=0;
		swap(ch1,ch2);
		v[ch0]^=1;v[ch1]^=1;v[ch2]^=1;
	}
}
inline void modify(int x){
	if(ls[x])return;
	pushdown(x);
	swap(ch0,ch1);swap(ch0,ch2);
	modify(ch0); 
}
int p[M],f[N];
inline void dfs(int x,int val,int dep){
	if(ls[x]){p[ls[x]]=val;return;}
	pushdown(x);
	for(int i=0;i<=2;i++)dfs(trie[x][i],val+i*f[dep],dep+1);
}
char s[KK];
inline void pre(){
	f[0]=1;
	for(int i=1;i<=n;i++){
		f[i]=f[i-1]*3;
	}
	for(int i=0;i<f[n];i++)ins(i);
}
int main(void){
	n=read();
	scanf("%s",s+1);
	int len=strlen(s+1);
	pre();
	for(int i=1;i<=len;i++){
		if(s[i]=='0')v[1]^=1;
		else modify(1);
	} 
	dfs(1,0,0);
	for(int i=1;i<=num;i++)printf("%d ",p[i]);
	
	return 0;
}