其他分享
首页 > 其他分享> > abc252

abc252

作者:互联网

\(\textbf{G.}\)

设 \(f(l,r),g(l,r)\) 分别表示区间 \([l,r]\) 对应的树的数量及森林的数量.

则: \(f(l,r)=\sum\limits_{k=l+1}^{r}[k=r\text{ or }p_{k+1}>p_{l+1}]f(l+1,k)*g(k+1,r)\), \(g(l,r)=\sum\limits_{k=l}^{r}[k=r\text{ or }p_{k+1}>p_l]f(l,k)g(k+1,r)\).

解释: \(f\) 的转移中 \([k=r\text{ or }p_{k+1}>p_{l+1}]\) 是因为要求第 \(1\) 棵子树的根节点比第 \(2\) 棵子树的根节点小, \(g\) 的转移中 \([k=r\text{ or }p_{k+1}>p_l]\) 是因为要求当前子树的根节点比下一棵子树的根节点小.

#include<bits/stdc++.h>
using namespace std;

const int N = 500 + 5; const long long mod = 998244353;

long long f[N][N], g[N][N]; int p[N]; int n;

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) scanf("%d", &p[i]);

	memset(f, 0, sizeof(f)), memset(g, 0, sizeof(g));
	for(int i = 1; i <= n; i ++) f[i + 1][i] = g[i + 1][i] = 1;
	for(int i = 1; i <= n; i ++) f[i][i] = g[i][i] = 1;
	for(int l = n; l >= 1; l --){
		for(int r = l + 1; r <= n; r ++){
			for(int k = l + 1; k <= r; k ++) if(k == r || p[k + 1] > p[l + 1]) (f[l][r] += f[l + 1][k] * g[k + 1][r]) %= mod;
			for(int k = l; k <= r; k ++) if(k == r || p[k + 1] > p[l]) (g[l][r] += f[l][k] * g[k + 1][r]) %= mod;
		}
	}

	printf("%lld\n", f[1][n]);

	return 0;
}

\(\textbf{H.}\)

设 \(n_c\) 表示颜色 \(c\) 的个数. 则 \(\sum\limits_{c=1}^{m}n_c=n\), 故方案数为 \(\prod\limits_{c=1}^{m}n_c\in\mathcal{O}(3^{\frac{n}{3}})\).

所以考虑meet-in-middle. 预处理出 \(X,Y\) 表示 \(2\) 部分的 \(\text{xor}\) 值.

所以答案为: \(k\text{th}(x\text{ xor }y:x\in X,y\in Y)\). 这可以通过在01-Trie上二分做到 \(\mathcal{O}((|X|+|Y|)\log W)\).

故时间复杂度: \(\mathcal{O}(S\log W)\). 其中 \(S=\mathcal{O}(3^{\frac{n}{6}})\), 经过一些计算发现 \(\max S=2\cdot3^{11}=354294\).

#include<bits/stdc++.h>
using namespace std;

const int N = 70 + 5, M = 70 + 5; const int S = 354294 + 5;

int ch[S * 60][2], siz[S * 60]; int cnt = 1;

vector<long long> lis[M]; int m, n; long long k;

void divide(vector<vector<long long>> &P, vector<vector<long long>> &Q){
	vector<int> order; for(int c = 1; c <= m; c ++) order.push_back(c);
	sort(order.begin(), order.end(), [&](int c1, int c2){return lis[c1].size() > lis[c2].size();});

	P.clear(), Q.clear(); long long prodP = 1, prodQ = 1;
	for(int c : order){
		prodP *= lis[c].size(); P.push_back(lis[c]);
		if(prodP > prodQ) swap(prodP, prodQ), swap(P, Q);
	}
}

vector<long long> dfs(const vector<vector<long long>> val, int i){
	if(i == val.size()) return {0};
	vector<long long> res = dfs(val, i + 1), ans;
	for(long long _ : res) for(long long __ : val[i]) ans.push_back(_ ^ __);
	return ans;
}

int main(){
	scanf("%d%d%lld", &n, &m, &k);
	for(int i = 1; i <= n; i ++){int c; long long val; scanf("%d%lld", &c, &val); lis[c].push_back(val);}

	vector<vector<long long>> P, Q; divide(P, Q);
	vector<long long> X = dfs(P, 0), Y = dfs(Q, 0);

	for(long long x : X){
		int u = 1; siz[u] ++;
		for(int bit = 59; bit >= 0; bit --){
			int xx = (x >> bit) & 1;
			if(!ch[u][xx]) ch[u][xx] = ++ cnt;
			u = ch[u][xx]; siz[u] ++;
		}
	}
	long long ans = 0; vector<int> U = vector<int>(Y.size(), 1);
	for(int bit = 59; bit >= 0; bit --){
		long long sum = 0;
		for(int i = 0; i < Y.size(); i ++){
			int u = U[i]; int yy = (Y[i] >> bit) & 1;
			sum += siz[ch[u][!yy]];
		}
		if(sum >= k){
			ans |= (1ll << bit);
			for(int i = 0; i < Y.size(); i ++){
				int u = U[i]; int yy = (Y[i] >> bit) & 1;
				U[i] = ch[u][!yy];
			}
		}
		else{
			k -= sum;
			for(int i = 0; i < Y.size(); i ++){
				int u = U[i]; int yy = (Y[i] >> bit) & 1;
				U[i] = ch[u][yy];
			}
		}
	}
	printf("%lld\n", ans);

	return 0;
}

标签:int,text,sum,long,vector,bit,abc252
来源: https://www.cnblogs.com/zhangmj2008/p/abc252.html