ABC 458 球盒模型|AC自动机|矩阵快速幂DP

D

对顶堆模板

题意

每次增加两个元素,问中位数,保证集合大小一直是奇数

分析

动态求中位数,直接对顶堆。pypypy的话sortedlist也可以,可惜cppcppcpp没有这种方便的库

c 复制代码
struct Set {
	const int kInf = 1e9 + 2077;
	std::multiset<int> less, greater;
	void init() {
		less.clear(), greater.clear();
		less.insert(-kInf), greater.insert(kInf);
	}
	void adjust() {
		while (less.size() > greater.size() + 1) {
			std::multiset<int>::iterator it = (--less.end());
			greater.insert(*it);
			less.erase(it);
		}
		while (greater.size() > less.size()) {
			std::multiset<int>::iterator it = greater.begin();
			less.insert(*it);
			greater.erase(it);
		}
	}
	void add(int val_) {
		if (val_ <= *greater.begin())
			less.insert(val_);
		else
			greater.insert(val_);
		adjust();
	}
	void del(int val_) {
		std::multiset<int>::iterator it = less.lower_bound(val_);
		if (it != less.end()) {
			less.erase(it);
		} else {
			it = greater.lower_bound(val_);
			greater.erase(it);
		}
		adjust();
	}
	int get_middle() {
		return *less.rbegin();
	}
};
void solve() {
	int x, q;
	cin >> x >> q;

	Set s;
	s.init();
	s.add(x);
	rep(i, 1, q) {
		int a, b;
		cin >> a >> b;
		s.add(a);
		s.add(b);
		cout << s.get_middle() << '\n';
	}
}

E

组合数学 隔板法

题意

1,2,31,2,31,2,3分别x1,x2,x3x_1,x_2,x_3x1,x2,x3个,组成一个序列,要求相邻元素差的绝对值不超过111。问有多少个不同序列?

分析

注意到不满足这个要求的只有1,31,31,3直接相邻,所以可以把222当成隔板,吧1,31,31,3隔开。有x2x_2x2个222,则划分出x2+1x_2+1x2+1个区域,每个区域里要么空,要么全是111,要么全是333

那么枚举x1x_1x1有iii段,从x2+1x_2+1x2+1个位置里选iii段给111,方案数C(x1+1,i)C(x_1+1,i)C(x1+1,i),把x1x_1x1个111放进iii个位置里,不妨设不允许空位,这是经典球盒问题,方案数C(x1−1,i−1)C(x_1-1,i-1)C(x1−1,i−1),剩下的x2+1−ix_2+1-ix2+1−i位置拿来放x3x_3x3个333,允许空盒,方案数C(x2+1−i+x3−1,x3)C(x_2+1-i+x_3-1,x_3)C(x2+1−i+x3−1,x3)

实现

c 复制代码
void solve() {
	int x, y, z;
	cin >> x >> y >> z;
	int ans = 0;

	int box = y + 1;
	rep(i, 1, x) {
		ans += C(y + 1, i) * C(x - 1, i - 1) % M2 * C(box - i + z - 1, z) % M2;
		ans %= M2;
	}
	cout << ans;


}

F

AC 自动机 矩阵快速幂优化DPDPDP

题意

和给101010个串,长度不超过101010,问长度为1e91e91e9的,不含这些串作为子串的串个数?

分析

模式串不能出现,问合法串数,这可以KMPKMPKMP思想,维护模式串匹配到哪了,如果完成了一个完整的模式串匹配,那么从这个状态开始,接下来到的状态,都标记为非法。

这样我们构建了一个自动机,上面一些节点是非法的。把非法节点删掉,得到的子图是一个只接受合法串的自动机。求走nnn步的方案数,在这个自动机上从初态开始,转移nnn次,每个点保存到达这个状态的方案数,然后对所有状态方案数求和。

这里有多个模式串的话,KMPKMPKMP拓展到ACACAC自动机即可。先ACACAC自动机建出来,然后把这个自动机对应的图写成一个邻接矩阵的形式,求n=1e9n=1e9n=1e9步的结果,对这个矩阵做矩阵快速幂即可。

c 复制代码
struct Aho_Corasick_Automaton {
	queue<int> q;
	int c[N][26], val[N], fail[N], cnt;

	void init() {
		memset(c, 0, sizeof(c));
		memset(val, 0, sizeof(val));
		memset(fail, 0, sizeof(fail));
		cnt = 0;
	}

	void ins(string &s) {
		int len = s.size();
		int now = 0;
		for (int i = 0; i < len; i++) {
			int v = s[i] - 'a';
			if (!c[now][v]) c[now][v] = ++cnt;
			now = c[now][v];
		}
		val[now]++;
	}

	void build() {
		for (int i = 0; i < 26; i++) if (c[0][i]) fail[c[0][i]] = 0, q.push(c[0][i]);
		while (!q.empty()) {
			int u = q.front();
			q.pop();

			val[u] |= val[fail[u]];

			for (int i = 0; i < 26; i++)
				if (c[u][i]) fail[c[u][i]] = c[fail[u]][i], q.push(c[u][i]);
				else c[u][i] = c[fail[u]][i];
		}
	}
} AC;


typedef vector<vector<long long>> Matrix;

// 矩阵乘法
Matrix multiply(const Matrix &A, const Matrix &B, long long MOD) {
	int n = A.size();
	int m = B[0].size();
	int k = B.size();
	Matrix C(n, vector<long long>(m, 0));

	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			for (int l = 0; l < k; ++l) {
				C[i][j] = (C[i][j] + A[i][l] * B[l][j] % MOD) % MOD;
			}
		}
	}
	return C;
}

// 矩阵快速幂
Matrix power(Matrix A, long long p, long long MOD) {
	int n = A.size();
	Matrix result(n, vector<long long>(n, 0));

	// 初始化结果矩阵为单位矩阵
	for (int i = 0; i < n; ++i) {
		result[i][i] = 1;
	}

	while (p) {
		if (p % 2 == 1) {
			result = multiply(result, A, MOD);
		}
		A = multiply(A, A, MOD);
		p /= 2;
	}

	return result;
}
void solve() {
	int n, k;
	cin >> n >> k;

	AC.init();
	rep(i, 1, k) {
		string s;
		cin >> s;
		AC.ins(s);
	}

	AC.build();

	int tot = AC.cnt + 1;

	Matrix f(tot, vi(tot));
	rep(i, 0, tot - 1) {
		if (AC.val[i])continue;
		rep(j, 0, 25) {
			int nxt = AC.c[i][j];
			if (!AC.val[nxt]) {
				f[i][nxt]++;
			}
		}
	}

	f = power(f, n, M2);
	int ans = 0;
	rep(i, 0, tot - 1) {
		if (!AC.val[i]) {
			ans = (ans + f[0][i]) % M2;
		}
	}
	cout << ans;
}
相关推荐
m0_547486662 小时前
华南农业大学《线性代数》期末试卷及答案2015-2023学年
线性代数·抽象代数·期末试卷·华南农业大学
NashSKY6 小时前
波束成形MVDR (最小方差无失真响应) 算法数学原理解析
算法·矩阵
__Coffee__8 小时前
封装矩阵结构体
线性代数·算法·矩阵
05候补工程师8 小时前
【考研线代笔记】相似对角化与实对称矩阵:判定法则、计算技巧与物理本质
笔记·线性代数·考研·矩阵
NashSKY10 小时前
用舒尔补给平面圆“配方“:从齐次矩阵形式到圆心 + 半径形式
线性代数·平面·矩阵
05候补工程师10 小时前
【线性代数】核心考点:二次型、矩阵三大关系综合与正定矩阵判别法
笔记·线性代数·考研·算法·矩阵
AI科技星10 小时前
基于全域数学0-1-∞体系的1.237宇宙临界常数及时空超导统一理论
c语言·开发语言·线性代数·量子计算·agi
2601_9577875820 小时前
企业级内容矩阵的安全合规体系构建与技术实现
大数据·安全·矩阵
2601_957787581 天前
数据驱动的多平台内容矩阵运营效果分析与闭环优化技术
大数据·人工智能·矩阵