Loading

2025.9.2 测试

ABC*_E

根据极值分治即可,可以用二阶差分做到 \(O(n)\)
一阶差分通过启发式可以做到 \(O(n\log n)\)

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = a; i <= b; ++i)
#define rep(i, a, b) for (int i = a; i >= b; --i)
#define cmx(a, b) std::max(a, b)
#define cmn(a, b) std::min(a, b)
#define gmx(a, b) a = cmx(a, b)
#define gmn(a, b) a = cmn(a, b)

template <typename T>
void _debug(const T& t) { std::cerr << t << '\n'; }
template <typename T, typename... Args>
void _debug(const T& t, const Args&...res) { std::cerr << t << ' '; _debug(res...); }
#define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)

const int LN = 2e5 + 7;
typedef long long ll;
typedef std::pair<int, int> PII;

int n, a[LN], st[LN][21], lg[LN]; ll ans[LN];

int upd(int u, int v) { return a[u] >= a[v] ? u : v; }
void init() {
	lep(j, 1, 20) lep(i, 1, n - (1 << j) + 1)
		st[i][j] = upd(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
	lep(i, 2, n) lg[i] = lg[i >> 1] + 1;
}
int qry(int l, int r) { int k = lg[r - l + 1], p = upd(st[l][k], st[r - (1 << k) + 1][k]); return p; }
void solve(int l, int r) {
	if (l > r) return; int p = qry(l, r);
	if (p - l <= r - p) lep(i, l, p) ans[p - i + 1] += a[p], ans[r - i + 2] -= a[p];
	else lep(i, p, r) ans[i - p + 1] += a[p], ans[i - l + 2] -= a[p];
	solve(l, p - 1), solve(p + 1, r);
}

int main() {
#ifndef DEBUG
	freopen("a.in", "r", stdin);
	freopen("a.out","w",stdout);
#endif
	std::ios::sync_with_stdio(false),
	std::cin.tie(nullptr), std::cout.tie(nullptr);

	std::cin >> n;
	lep(i, 1, n) std::cin >> a[i], st[i][0] = i;
	init(), solve(1, n);
	lep(i, 2, n) ans[i] += ans[i - 1];
	lep(i, 1, n) std::cout << ans[i] << '\n';
	return 0;
}


P4370 [Code+#4] 组合数问题2

发现如果直接用堆的话无法比较大小,而虽然 \(\binom{n}{m}\) 很大,但 \(n\le 10^6\)\(\log_2\binom{n}{m}\) 很小。
\(\log{ab} = \log a + \log b\) ,所以 \(\log10^6!\le 20\times 10^6\) ,可以直接用 long double 存下来比较。

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = a; i <= b; ++i)
#define rep(i, a, b) for (int i = a; i >= b; --i)
#define il inline
#define cmx(a, b) std::max(a, b)
#define cmn(a, b) std::min(a, b)
#define gmx(a, b) a = cmx(a, b)
#define gmn(a, b) a = cmn(a, b)

template <typename T>
void _debug(const T& t) { std::cerr << t << '\n'; }
template <typename T, typename... Args>
void _debug(const T& t, const Args&...res) { std::cerr << t << ' '; _debug(res...); }
#define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)

const int LN = 1e6 + 7;
const int mod = 1e9 + 7;
typedef long double ld;
typedef long long ll;
typedef std::pair<int, int> PII;

struct node {
	ld gl; int n, m;
	friend bool operator < (const node&x, const node& y) { return x.gl < y.gl; }
};
int n, k, ans, fac[LN], inv[LN]; std::priority_queue <node> q;
ld fra[LN]; std::set<PII> S;

il int add(int u, int v) { return u + v >= mod ? u + v - mod : u + v; }
il void upa(int& u, int v) { u = add(u, v); }
il int mul(ll u, ll v) { return u * v >= mod ? u * v % mod : u * v; }
il void upm(int& u, int v) { u = mul(u, v); }
int MyPow(int a, int b) { int ans = 1; for (; b; b >>= 1, a = mul(a, a)) if (b & 1) upm(ans, a); return ans; }
ld fC(int n, int m) { return fra[n] - fra[m] - fra[n - m]; }
int C(int n, int m) { return mul(mul(fac[n], inv[m]), inv[n - m]); }

int main() {
	std::ios::sync_with_stdio(false),
	std::cin.tie(nullptr), std::cout.tie(nullptr);
	
	std::cin >> n >> k;
	fac[0] = 1; lep(i, 1, n) fac[i] = mul(fac[i - 1], i), fra[i] = std::log(i) + fra[i - 1];
	inv[n] = MyPow(fac[n], mod - 2);
	rep(i, n, 1) inv[i - 1] = mul(inv[i], i);
	
	q.push({fC(n, n / 2), n, n / 2}), S.insert({n, n / 2});
	while (k--) {
		auto u = q.top(); q.pop();
		int n = u.n, m = u.m; upa(ans, C(n, m));
		if (m and !S.count({n, m - 1})) S.insert({n, m - 1}), q.push({fC(n, m - 1), n, m - 1});
		if (m < n and !S.count({n, m + 1})) S.insert({n, m + 1}), q.push({fC(n, m + 1), n, m + 1});
		if (n and m < n and !S.count({n - 1, m})) S.insert({n - 1, m}), q.push({fC(n - 1, m), n - 1, m});
	}
	std::cout << ans << '\n';
	return 0;
}

P8386 [PA 2021] Od deski do deski

合法序列应该形如 a...ab...bc...c,对于一个中间状态 a...ab...bc...cd.. ,后接 abcd 的任意一种都是合法的。
\(f[i,j,1/0]\) 表示长度为 \(i\) ,向后接 \(j\) 种颜色会变成合法的,且为合法/不合法的方案数。
易得转移:

\[\left\{\begin{matrix} (f[i,j,0] + f[i,j,1])\times j\rightarrow f[i+1,j,1]\\ f[i,j,0] \times (m-j)\rightarrow f[i+1,j,0]\\ f[i,j,1]\times (m-j)\rightarrow f[i+1,j+1,0] \end{matrix}\right. \]

点击查看

#include <bits/stdc++.h>
#define lep(i, a, b) for (int i = a; i <= b; ++i)
#define rep(i, a, b) for (int i = a; i >= b; --i)
#define cmx(a, b) std::max(a, b)
#define cmn(a, b) std::min(a, b)
#define gmx(a, b) a = cmx(a, b)
#define gmn(a, b) a = cmn(a, b)

template <typename T>
void _debug(const T& t) { std::cerr << t << '\n'; }
template <typename T, typename... Args>
void _debug(const T& t, const Args&...res) { std::cerr << t << ' '; _debug(res...); }
#define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__)

const int LN = 3000 + 7;
const int mod = 1e9 + 7;
typedef long long ll;
typedef std::pair<int, int> PII;

int n, m, f[LN][LN][2];

int add(int u, int v) { return u + v >= mod ? u + v - mod : u + v; }
void upa(int& u, int v) { u = add(u, v); }
int mul(ll u, ll v) { return u * v >= mod ? u * v % mod : u * v; }
void upm(int& u, int v) { u = mul(u, v); }

int main() {

	std::ios::sync_with_stdio(false),
	std::cin.tie(nullptr), std::cout.tie(nullptr);
	
	std::cin >> n >> m;
	f[0][0][1] = 1;
	lep(i, 0, n - 1) lep(j, 0, n - 1) {
		upa(f[i + 1][j][1], mul(add(f[i][j][0], f[i][j][1]), j)),
		upa(f[i + 1][j][0], mul(f[i][j][0], m - j)),
		upa(f[i + 1][j + 1][0], mul(f[i][j][1], m - j));
	}
	int ans = 0;
	lep(i, 0, n) upa(ans, f[n][i][1]);
	std::cout << ans << '\n';
	return 0;
}

T4(因版权原因不公开)

posted @ 2025-09-02 15:24  qkhm  阅读(9)  评论(0)    收藏  举报