agc044c&10.13 T2
阿新 • • 發佈:2021-10-13
題意:給定\(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; }