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;
}
posted @ 2021-10-13 20:30  xxbzzyw  阅读(56)  评论(0)    收藏  举报