2025 ICPC 网络赛2 DE

D. Arcane Behemoths

数学。

\(n=5\) 为例,考虑按顺序删掉后,留下最后一个数中各个数产生的贡献:

a₁ a₂ a₃ a₄ a₅
a b c d e
a+e b+e c+e d+e
a+d+2e b+d+2e c+d+2e
a+c+2d+4e b+c+2d+4e
a+b+2c+4d+8e

由此可知对于 \(i\) 位置系数 \(F=1,1,2,4,8...2^{n-2}(n\ge 2)\),那么该序列的产生的贡献即是排序后 $\sum_{i=1}^n a_i \times F_i $。

考虑第 \(i\) 个数在所有子集中产生的总贡献,首先要在比它小的 \(i-1\) 个数中选取 \(j-1\) 个数以确保它可能排在子集的第 \(j\) 个位置,在 \(j\) 位置的系数为 \(F_j\),且比它大的 \(n-i\) 个数可以任意选择是否进入序列,所以第 \(i\) 个数产生的总贡献为 \(\sum_{j=1}^i \binom{i-1}{j-1}\cdot F_j\cdot2^{n-i}\)

考虑化简 \(\sum_{j=1}^i \binom{i-1}{j-1}\cdot F_j:\)

\[\begin{align*} \sum_{j=1}^i \binom{i-1}{j-1}\cdot F_j&=\sum_{j=2}^i \binom{i-1}{j-1}\cdot F_j + \binom{i-1}{0} F_1\\ &= \sum_{j=2}^i \binom{i-1}{j-1}\cdot F_j + 1\\ 令 k = j - 1,且j \ge 2 时,有 F_j=2^{j-2}, 则有:\\ &=\sum_{k=1}^{i-1}\binom{i-1}{k}2^{k-1} + 1\\ &=\frac{\sum_{k=1}^{i-1}\binom{i-1}{k}2^{k}}{2}+1\\ 根据二项式定理有 (1+2)^{i-1}=\sum_{k=0}^{i-1}\binom{i-1}{k}2^k,则有:\\ &= \frac{\sum_{k=1}^{i-1}\binom{i-1}{k}2^{k}+\binom{i-1}{0}2^0-\binom{i-1}{0}2^0}{2}+1\\ &= \frac{(1+2)^{i-1}-1}{2}+1\\ &=\frac{3^{i-1}+1}{2} \end{align*} \]

所以单个元素的贡献为 \(a_i\cdot\frac{3^{i-1}+1}{2}\cdot 2^{n-i}.\)

代码中 Z 类型为自动取模类。

点击查看代码
void solve() {

	int n;
	cin >> n;

	vector<int> a(n + 1);
	for (int i = 1; i <= n; i += 1) {
		cin >> a[i];
	}

	sort(a.begin() + 1, a.end());

	Z ans = 0;
	for (int i = n; i >= 1; i -= 1) {
		ans += Z(a[i]) * (power<Z>(3, i - 1) + 1) / 2 * power<Z>(2, n - i);
	}

	cout << ans << "\n";

}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

E. Zero

矩阵快速幂优化 dp。

考虑第一个数任意选,有 \(2^m\) 种选择,那么第 \(2\sim n-1\) 就有 \(2^{m-1}\) 种选择,因为最后要和前面的异或结果为 \(0\) ,所以最后一位是固定的,但是此时最后一位可能和倒数第二位相等,所以 \(1\sim n-2\) 的异或结果就肯定为 \(0\),设 \(f_i\) 表示序列长度为 \(i\) 时的答案,那么转移方程为:

\[f_n = 2^m\cdot (2^m - 1)^{n-2} - f_{n-2} \cdot (2^m - 1) \]

注意到 \(n\) 最大为 \(1\times10^9\),那么可以采取矩阵快速幂优化转移。
则有:

\[\begin{bmatrix} f_{n} \\ f_{n-1} \\ f_{n-2} \\ (2^m-1)^{n-1} \end{bmatrix} = \begin{bmatrix} 0 & -(2^m-1) & 0 & 2^m \\ 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 2^m-1 \end{bmatrix} \begin{bmatrix} f_{n-1} \\ f_{n-2} \\ f_{n-3} \\ (2^m-1)^{n-2} \end{bmatrix} \]

代码中 Z 类型为自动取模类。

点击查看代码
using Z = ModInt<MOD[0]>;

template<class T>
struct Matrix {
	i64 N;
	vector<vector<T>> A;
	Matrix() : N(0) {}
	Matrix(int n) : N(n), A(n, vector<T>(n, 0)) {}
	Matrix(const vector<vector<T>>& mat) {
		assert(!mat.empty() && !mat[0].empty()); // 确保非空
		N = mat.size();
		A = mat;
	}

	const vector<T>& operator[](int i) const {
		return A[i];
	}

	Matrix operator*(const Matrix &b) const {
		assert(N == b.N);
		Matrix res(N);

		for (int i = 0; i < N; i++) {
			for (int k = 0; k < N; k++) {
				T tmp = A[i][k];
				if (tmp == 0) {
					continue;
				}
				for (int j = 0; j < N; j++) {
					res.A[i][j] += tmp * b.A[k][j];
				}
			}
		}
		return res;
	}

	//快速幂实现
	Matrix power(Matrix res, i64 k) const {
		Matrix base = *this;
		while (k) {
			if (k & 1) {
				res = res * base;
			}
			base = base * base;
			k >>= 1;
		}
		return res;
	}
};

void solve() {

	int n, m;
	cin >> n >> m;

	vector<Z> f(4);
	Z m2 = power<Z>(2, m);
	f[1] = 1, f[2] = 0;
	f[3] = m2 * (m2 - 1) - (m2 - 1);

	if (n <= 3) {
		cout << f[n] << "\n";
		return;
	}

	vector a(4, vector<Z>(4));
	auto base = a;
	a[0][1] = 1 - m2, a[0][3] = m2;
	a[1][0] = 1;
	a[2][1] = 1;
	a[3][3] = m2 - 1;
	base[0][0] = f[3], base[1][0] = f[2];
	base[2][0] = f[1], base[3][0] = (m2 - 1) * (m2 - 1);

	Matrix<Z> A(a);
	A = A.power(A, n - 4);
	A = A * base;

	cout << A[0][0] << "\n";

}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}
posted @ 2025-09-15 17:22  Ke_scholar  阅读(91)  评论(0)    收藏  举报