ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

abc252

2022-09-08 16:30:45  阅读:176  来源: 互联网

标签:int text sum long vector bit 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有