倍数限制(multiple)
注意是一个排列,我们考虑双指针,那么没一个数只会进出两次,由于是排列,所以就是调和集数的时间复杂度
#include <bits/stdc++.h>using namespace std;#define int long longconst int N = 1e6 + 5;int t, n, k, a[N], cnt[N], ans;bool vis[N];void Solve() {ans = 0;cin >> n >> k;for (int i = 1; i <= n; i++) {cin >> a[i];cnt[i] = vis[i] = 0;}for (int i = 1, j = 1, tot = 0; i <= n; i++) {while (j <= n && tot + cnt[a[j]] <= k) {tot += cnt[a[j]];vis[a[j]] = true;for (int l = a[j] * 2; l <= n; l += a[j]) {cnt[l]++;}j++;}ans = max(ans, (j - i));for (int l = a[i] * 2; l <= n; l += a[i]) {if (vis[l]) {tot--;}cnt[l]--;}vis[a[i]] = false;}cout << ans << "\n";
}signed main() {ios::sync_with_stdio(0);cin.tie(0);freopen("multiple.in", "r", stdin);freopen("multiple.out", "w", stdout);cin >> t;while (t--) {Solve();}return 0;
}
硬币问题(coin)
我们可以选择面值最小的硬币面值,以它作为基准,我们只用考虑模最小值能否被凑出,我们可以跑一边 \(dij\) 记录将一个数凑出最小要多少倍的基准
#include <bits/stdc++.h>using namespace std;#define int long longconst int N = 1e6 + 5;struct dv {int d, v;bool operator < (const dv &_y) const {return d > _y.d;}
};int n, m, a[N], cnt, dis[N], mod = 100000000, ans;void dij() {priority_queue<dv> q;dis[0] = 1;q.push({1, 0});while (!q.empty()) {if (dis[q.top().v] < q.top().d) {q.pop();continue;}auto cur = q.top();q.pop();for (int i = 1; i <= n; i++) {int v = (cur.v + a[i]) % mod;if (dis[v] > dis[cur.v] + ((cur.v + a[i]) / mod)) {dis[v] = dis[cur.v] + ((cur.v + a[i]) / mod);q.push({dis[v], v});}}}
}signed main() {freopen("coin.in", "r", stdin);freopen("coin.out", "w", stdout);cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> a[i];mod = min(mod, a[i]);}fill(dis, dis + mod + 1, 2e18);dij();for (int i = 0; i < mod; i++) {if (dis[i] > 1e18) {continue;}int tmp = i + (dis[i] - 1) * mod;if (!i) {tmp += mod;}ans += max(0ll, (m - tmp + 1 + mod - 1) / mod);}cout << ans;return 0;
}
区间寻找(interval)
二分加线段树即可
#include <bits/stdc++.h>using namespace std;#define int long longusing Pii = pair<__int128, __int128>;const int N = 1e5 + 5;int n, q, a[N];__int128 tr[3][N * 4], sum[N];void build(int i, int l, int r) {if (l == r) {tr[1][i] = sum[l];tr[2][i] = sum[l];return ;}int mid = (l + r) >> 1;build(i * 2, l, mid);build(i * 2 + 1, mid + 1, r);tr[1][i] = max(tr[1][i * 2], tr[1][i * 2 + 1]);tr[2][i] = min(tr[2][i * 2], tr[2][i * 2 + 1]);
}Pii query(int i, int l, int r, int x, int y) {if (x > y) {return {-1e18, 1e18};}if (l > y || r < x) {return {-1e18, 1e18};}if (l >= x && r <= y) {return {tr[1][i], tr[2][i]};}int mid = (l + r) >> 1;Pii tmp1 = query(i * 2, l, mid, x, y), tmp2 = query(i * 2 + 1, mid + 1, r, x, y);return {max(tmp1.first, tmp2.first), min(tmp1.second, tmp2.second)};
}void Solve() {int w, x, y, u, d;cin >> w >> x >> y >> u >> d;u -= w, d -= w;u += sum[x - 1];d += sum[x - 1];//cout << u << " " << d << "\n";int l = y - 1, r = n;while (l < r) {int mid = (l + r + 1) >> 1;Pii tmp = query(1, 1, n, x, mid);if (tmp.first <= u && tmp.second >= d && tmp.first >= tmp.second) {l = mid;}else r = mid - 1;}if (l < y) {cout << "None\n";}else cout << l << "\n";
}signed main() {ios::sync_with_stdio(0);cin.tie(0);freopen("interval.in", "r", stdin);freopen("interval.out", "w", stdout);cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];sum[i] = sum[i - 1] + a[i];}build(1, 1, n);Pii tmp = query(1, 1, n, 2, 6);while (q--) {Solve();}return 0;
}
期望长度(ex)
单调栈
#include <bits/stdc++.h>using namespace std;#define int long longconst int N = 1e5 + 5, mod = 1e9 + 7;int n, a[N], l[N], r[N], ans1[N], ans2[N];int mypow(int a, int b) {int ans = 1;while (b) {if (b & 1) {ans = ans * a % mod;}a = a * a % mod;b >>= 1;}return ans;
}signed main() {ios::sync_with_stdio(0);cin.tie(0);freopen("ex.in", "r", stdin);freopen("ex.out", "w", stdout);cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];}stack<int> stk;for (int i = 1; i <= n; i++) {while (!stk.empty() && a[stk.top()] <= a[i]) {stk.pop();}if (!stk.empty()) {l[i] = stk.top() + 1;}else l[i] = 1;stk.push(i);}while (!stk.empty()) {stk.pop();}for (int i = n; i >= 1; i--) {while (!stk.empty() && a[stk.top()] < a[i]) {stk.pop();}if (!stk.empty()) {r[i] = stk.top() - 1;}else r[i] = n;stk.push(i);}for (int i = 1; i <= n; i++) {ans1[a[i]] += ((r[i] - i + 2) * (r[i] - i + 1) / 2) * (i - l[i] + 1);ans1[a[i]] += ((i - l[i] + 2) * (i - l[i] + 1) / 2) * (r[i] - i + 1);ans2[a[i]] += (i - l[i] + 1) * (r[i] - i + 1);ans1[a[i]] = ((ans1[a[i]] - (i - l[i] + 1) * (r[i] - i + 1) % mod) % mod + mod) % mod;ans1[a[i]] %= mod, ans2[a[i]] %= mod;}for (int i = 1; i <= n; i++) {cout << ans1[i] * mypow(ans2[i], mod - 2) % mod << "\n";}return 0;
}