#include<bits/stdc++.h>typedefunsignedlonglong ull;int n;
ull k;voidsolve(int n, ull k){if(!n)return;
ull mid =1ull<< n -1;if(k < mid)putchar('0'),solve(n -1, k);elseputchar('1'),solve(n -1, mid -1-(k - mid));}intmain(){
std::cin >> n >> k;solve(n, k);returnputs(""),0;}
D1T2 brackets
Solution
令 cntu 表示根到 u 的路徑組成的括號序列,以 u 爲右端點的合法括號序列個數
那麼 ku 就等於根到 u 的路徑上所有點的 cnt 之和
易得如果存在 u 的一個深度最大的祖先 v 使得 v 到 u 的路徑組成的括號序列是合法括號序列
那麼 cntu=cntfav+1
對於求這個 v ,可以維護一個棧
從根到 u ,如果是左括號則直接加入,如果是右括號且棧不空則彈棧
那麼如果 u 爲右括號,那麼 v 爲這次彈出的括號對應的點
而對於求出所有的 u ,可以在對樹 DFS 的過程中維護這個棧,在 DFS 回溯時把棧操作也退回即可
O(n)
Code
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){
res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);if(bo) res =~res +1;}typedeflonglong ll;constint N =5e5+5;int n, fa[N], ecnt, nxt[N], adj[N], go[N], stk[N], top, cnt[N];char s[N];
ll sum[N], ans;voidadd_edge(int u,int v){
nxt[++ecnt]= adj[u]; adj[u]= ecnt; go[ecnt]= v;}voiddfs(int u){int tf =0;if(s[u]=='(') stk[++top]= u;elseif(top) cnt[u]= cnt[fa[tf = stk[top--]]]+1;
sum[u]= sum[fa[u]]+ cnt[u];
ans ^= sum[u]* u;for(int e = adj[u], v = go[e]; e; e = nxt[e], v = go[e])dfs(v);if(s[u]=='(') top--;elseif(tf) stk[++top]= tf;}intmain(){int x;read(n);scanf("%s", s +1); n =strlen(s +1);for(int i =2; i <= n; i++)read(x),add_edge(fa[i]= x, i);dfs(1);return std::cout << ans << std::endl,0;}
於是可以 DP :設 f[i][j] 表示前 i 個變量和爲 j 的方案數(j 可以爲負),轉移時枚舉下一個變量的取值
O(mn2)
Code
#include<bits/stdc++.h>template<classT>inlinevoidread(T &res){
res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);if(bo) res =~res +1;}constint N =105, E =205, M =2005, rqy =998244353;int n, m, a[N][M], f[N][E], sum[N], tmp[N], ans =1;inlinevoidadd(int&a,constint&b){
a += b;if(a >= rqy) a -= rqy;}inlinevoidsub(int&a,constint&b){
a -= b;if(a <0) a += rqy;}intmain(){read(n);read(m);for(int i =1; i <= n; i++) sum[i]=1;for(int i =1; i <= n; i++)for(int j =1; j <= m; j++)read(a[i][j]),add(sum[i], a[i][j]);for(int i =1; i <= n; i++) ans =1ll* ans * sum[i]% rqy;sub(ans,1);for(int i =1; i <= m; i++){for(int j =1; j <= n; j++) tmp[j]= sum[j],sub(tmp[j], a[j][i]),sub(tmp[j],1);for(int j =-n; j <= n; j++)for(int k =0; k <= n; k++)
f[k][j + n]=0;
f[0][n]=1;for(int j =1; j <= n; j++)for(int k =-n; k <= n; k++){add(f[j][k + n], f[j -1][k + n]);if(k >-n)add(f[j][k + n],1ll* f[j -1][k -1+ n]* a[j][i]% rqy);if(k < n)add(f[j][k + n],1ll* f[j -1][k +1+ n]* tmp[j]% rqy);}for(int j =1; j <= n; j++)sub(ans, f[n][j + n]);}return std::cout << ans << std::endl,0;}