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(因版权原因不公开)
时间仓促,如有错误欢迎指出,欢迎在评论区讨论,如对您有帮助还请点个推荐、关注支持一下