题解:P16822 [蓝桥杯 2026 国 Python B] 零段积分

世界机器还是太厉害了,来点唐唐做法。

\(x=\dfrac pq\)\(y=1-x\)

容易发现 \(l_il_{i+1}\) 的组合意义就是从相邻的连续 \(0\) 段中各选出一个 \(0\) 的方案数。根据期望的线性性,我们相当于要求

\[\sum_{1\leq i<j\leq n}P(i,j) \]

其中 \(P(i,j)\) 表示 \(i,j\) 处于相邻 \(0\) 段的概率。

\(len=j-i+1\),则 \([i,j]\) 一定是形如 \(0^a1^b0^c\)。考虑到 \(a+c=len-b\),不难得出

\[P(i,j)=\sum_{b=1}^{len-3}(len-b-1)x^by^{len-b} \]

上式显然只跟 \(len\) 有关,不妨设为 \(f_{len}\),则答案为

\[\sum_{len=3}^n(n-len+1)f_{len} \]

考虑 \(\mathcal{O}(n)\) 计算 \(f_{len}\)。不难想到递推,设

\[g_{len}=\sum_{b=1}^{len-2}x^by^{len-b} \]

套路地拆出来最后一项,容易得到递推式:

\[\begin{align*} f_{len}&=x^{len-2}y^2+y(f_{len-1}+g_{len-1})\\ g_{len}&=x^{len-2}y^2+yg_{len}-1 \end{align*} \]

递推的同时算出 \(x^{len-2}y^2\) 即可做到 \(\mathcal{O}(n)\)。可以通过本题。

进一步优化,考虑矩阵快速幂加速。容易想到要把 \(f,g,x^{len-1}\) 都加到矩阵里。至于 \((n-len+1)f_{len}\),套路地转化成二维前缀和:

\[\sum_{len=3}^n(n-len+1)f_{len}=\sum_{i=3}^n\sum_{j=3}^i f_j \]

于是设

\[\begin{align*} A_i&=\sum_{len=3}^i f_{len}\\ B_i&=\sum_{len=3}^i A_{len} \end{align*} \]

\(A,B\) 也加入矩阵中即可。

简单推一下矩阵。初始向量为

\[V=\begin{bmatrix} f_3\\ g_3\\ x^2\\ f_3\\ f_3 \end{bmatrix} \]

转移矩阵为

\[T=\begin{bmatrix} y & y & y^2 & 0 & 0\\ 0 & y & y^2 & 0 & 0\\ 0 & 0 & x & 0 & 0\\ y & y & y^2 & 1 & 0\\ y & y & y^2 & 1 & 1 \end{bmatrix} \]

直接计算 \(T^{n-3}V\) 即可。时间复杂度为 \(\mathcal{O}(\log{n})\)

主要代码
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using i128 = __int128;
using ui = unsigned int;
using ull = unsigned long long;
using u128 = unsigned __int128;
using ld = long double;
using pii = pair<int, int>;
const int mod = 1e9 + 7;

template<typename T> T lowbit(T x) { return x & -x; }
template<typename T> void chkMin(T &x, T y) { x = y < x ? y : x; }
template<typename T> void chkMax(T &x, T y) { x = x < y ? y : x; }
template<typename T> T add(T x, T y) { return (x += y) >= mod ? x - mod : x; }
template<typename T> T sub(T x, T y) { return (x -= y) < 0 ? x + mod : x; }
template<typename T> void cadd(T &x, T y) { (x += y) >= mod ? (x -= mod) : x; }
template<typename T> void csub(T &x, T y) { (x -= y) < 0 ? (x += mod) : x; }

int n, p, q;

template<int N, int M>
struct Matrix {
	array<array<int, M>, N> a;
	Matrix() {
		for (int i = 0; i < N; ++i) a[i].fill(0);
	}
	int &operator()(int i, int j) {
		return a[i][j];
	}
	int operator()(int i, int j) const {
		return a[i][j];
	}
	template<int P>
	friend Matrix<N, P> operator*(const Matrix<N, M> &lhs, const Matrix<M, P> &rhs) {
		Matrix<N, P> res;
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < P; ++j) {
				int s = 0;
				for (int k = 0; k < M; ++k) cadd<int>(s, (ull)lhs(i, k) * rhs(k, j) % mod);
				res(i, j) = s;
			}
		}
		return res;
	}
};

template<int N>
Matrix<N, N> idMat() {
	Matrix<N, N> res;
	for (int i = 0; i < N; ++i) res(i, i) = 1;
	return res;
}

template<int N>
Matrix<N, N> qpow(Matrix<N, N> a, int b) {
	Matrix<N, N> res = idMat<N>();
	for (; b; b >>= 1) {
		if (b & 1) res = res * a;
		a = a * a;
	}
	return res;
}

int qpow(int a, int b) {
	int res = 1;
	for (; b; b >>= 1) {
		if (b & 1) res = (ll)res * a % mod;
		a = (ll)a * a % mod;
	}
	return res;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> p >> q;
	int x = (ull)p * qpow(q, mod - 2) % mod, y = sub(1, x);
	Matrix<5, 1> V;
	V(0, 0) = V(1, 0) = V(3, 0) = V(4, 0) = (ull)x * y % mod * y % mod;
	V(2, 0) = (ull)x * x % mod;
	Matrix<5, 5> T;
	T(0, 0) = T(0, 1) = T(1, 1) = T(3, 0) = T(3, 1) = T(4, 0) = T(4, 1) = y;
	T(0, 2) = T(1, 2) = T(3, 2) = T(4, 2) = (ull)y * y % mod;
	T(2, 2) = x;
	T(3, 3) = T(4, 3) = T(4, 4) = 1;
	cout << (n < 3 ? 0 : (qpow(T, n - 3) * V)(4, 0));
	return 0;
}
posted @ 2026-06-07 15:44  P2441M  阅读(8)  评论(0)    收藏  举报