2025/8/4 模拟赛总结
\(100+20+65+20=205\),暴力挂了 \(55\) 分?
洛谷 P10185,之前做过。用二项式定理化简一下式子,直接算即可
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int kMaxN = 2e5 + 5;
const LL kP = 1e9 + 7;
LL n, a[kMaxN], v[kMaxN], p, ans;
LL P(LL x, LL y, LL ret = 1) {
for (; y; (y & 1) && ((ret *= x) %= kP), (x *= x) %= kP, y >>= 1) {
}
return ret;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i], (p += a[i]) %= (kP - 1);
}
for (int i = 1; i <= n; i++) {
cin >> v[i], (ans += ((P(v[i] + 1, a[i]) - 1 + kP) % kP) * P(2, (p - a[i] + kP - 1) % (kP - 1)) % kP) %= kP;
}
cout << ans << '\n';
return 0;
}
因为因数成对出现,答案可以用总选择方式除以 \(2\) 来算。注意要特殊判断乘积刚好是 \(n^m\) 的情况
// BLuemoon_
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int kMaxN = 1.5e3 + 5, kMaxM = 205, kMaxL = 1e5 + 5;
const LL kP = 998244353;
LL n, m, tot, ans = 1, s[kMaxL], f[kMaxL];
multiset<LL> g;
LL P(LL x, LL y, LL ret = 1) {
for (; y; (y & 1) && ((ret *= x) %= kP), (x *= x) %= kP, y >>= 1) {
}
return ret;
}
LL Calc(LL l, LL r) { return (s[r] - (l - 1 < 0 ? 0 : s[l - 1]) + kP) % kP; }
LL Solve(LL x) {
fill(s, s + x * m + 1, 1), fill(f, f + x * m + 1, 0), f[0] = 1;
for (int i = 1; i <= m << 1; i++) {
for (int j = x * m; j; j--) {
f[j] = Calc(j - x, j);
}
for (int j = 1; j <= x * m; j++) {
s[j] = (s[j - 1] + f[j]) % kP;
}
}
return f[x * m];
}
void F(LL tmp = n) {
for (LL i = 2, cnt = 0; i * i <= tmp; i++, cnt = 0) {
if (tmp % i == 0) {
for (; tmp % i == 0; tmp /= i, cnt++) {
}
g.insert(cnt);
}
}
tmp > 1 && (g.insert(1), 0);
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (LL i = 1; i * i <= n; i++) {
if (n % i == 0) {
tot++, (i * i != n) && (tot++);
}
}
F();
for (LL i : g) {
(ans *= Solve(i)) %= kP;
}
cout << ((ans + P(tot, m << 1)) % kP) * P(2, kP - 2) % kP << '\n';
return 0;
}
先考虑 \(O(n^2)\) 的 dp,将每个点离散化后选择的两个集合分界线一定是一个折线。于是可以枚举每个点从下还是从左转移过来。这个过程可以用线段树优化
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int kMaxN = 4e5 + 5;
struct P {
LL x, y, v;
} c[kMaxN];
LL n, T, sum, tot, p[kMaxN], f[kMaxN], g[kMaxN], ans;
vector<LL> id[kMaxN];
struct Sgt {
LL t[kMaxN << 2], tag[kMaxN << 2];
void pushup(LL x) { t[x] = max(t[x << 1], t[x << 1 | 1]); }
void addtag(LL x, LL v) { t[x] += v, tag[x] += v; }
void pushdown(LL x) { tag[x] && (addtag(x << 1, tag[x]), addtag(x << 1 | 1, tag[x]), tag[x] = 0); }
void build(LL x, LL l, LL r) {
t[x] = 0, tag[x] = 0;
if (l == r) {
return;
}
int mid = l + r >> 1;
build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r);
pushup(x);
}
void update(LL x, LL l, LL r, LL L, LL R, LL v) {
if (L <= l && r <= R) {
return addtag(x, v), void();
}
pushdown(x);
int mid = l + r >> 1;
L <= mid && (update(x << 1, l, mid, L, R, v), 0);
mid < R && (update(x << 1 | 1, mid + 1, r, L, R, v), 0);
pushup(x);
}
LL query(LL x, LL l, LL r, LL L, LL R, LL ret = -1e18) {
if (L <= l && r <= R) {
return t[x];
}
pushdown(x);
int mid = l + r >> 1;
L <= mid && (ret = max(ret, query(x << 1, l, mid, L, R)));
R > mid && (ret = max(ret, query(x << 1 | 1, mid + 1, r, L, R)));
return ret;
}
} tr, tr2;
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin.tie(0)->ios::sync_with_stdio(0);
for (cin >> T; T; T--, tot = sum = ans = 0) {
cin >> n;
for (LL i = 1, a, b; i <= n; i++) {
cin >> c[i].x >> c[i].y >> a >> b, sum += a, c[i].v = b - a, p[++tot] = c[i].x, p[++tot] = c[i].y;
}
p[++tot] = 0, sort(p + 1, p + 1 + tot), tot = unique(p + 1, p + 1 + tot) - p - 1;
for (int i = 1; i <= n; i++) {
c[i].x = lower_bound(p + 1, p + 1 + tot, c[i].x) - p, c[i].y = lower_bound(p + 1, p + 1 + tot, c[i].y) - p;
}
for (int i = 1; i <= tot; i++) {
id[i].clear();
}
for (int i = 1; i <= n; i++) {
id[c[i].x].push_back(i);
}
tr.build(1, 1, tot), tr2.build(1, 1, tot);
for (int i = 1; i <= n; i++) {
tr2.update(1, 1, tot, c[i].y, tot, c[i].v), tr.update(1, 1, tot, c[i].y, tot, -c[i].v);
}
f[1] = 0;
for (int i = 2; i <= tot; i++) {
f[i] = -1e18, tr.update(1, 1, tot, i, i, -1e18);
}
for (int i = 1; i <= tot; i++) {
for (LL k : id[i]) {
LL j = c[k].y;
g[j] = f[j], f[j] = max(f[j], tr.query(1, 1, tot, 1, j - 1) + tr2.query(1, 1, tot, j, j)), ans = max(ans, f[j]);
}
for (LL k : id[i]) {
LL j = c[k].y;
tr.update(1, 1, tot, j, j, f[j] - g[j]), tr2.update(1, 1, tot, j, tot, -c[k].v), tr.update(1, 1, tot, j, tot, c[k].v);
}
}
cout << sum + ans << '\n';
}
return 0;
}
TBD...

浙公网安备 33010602011771号