T1. 美克斯
排列的性质非常优秀,考虑利用排列的性质快速求解。
注意到 \(\operatorname{mex}(S)\) 是 \(S\) 内没有出现的最小的自然数,又因为这是一个 \(0 \sim n-1\) 的排列,那么 \(\{a_l, a_{l+1}, \cdots, a_r\}\) 中未出现的自然数可以理解为 \(a_1, a_2, \cdots, \cdots, a_{l-1}\),以及 \(a_{r+1}, \cdots, a_{n-1}, a_n\),函数值也就是这些未出现的自然数中的最小值。
所以维护前后缀的最小值就能 \(O(N)\) 回答询问。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, q;
cin >> n >> q;
vector<int> a(n);
rep(i, n) cin >> a[i];
vector<int> pref(n+1, n), suff(n+1, n);
rep(i, n) pref[i+1] = min(pref[i], a[i]);
for (int i = n-1; i >= 0; --i) suff[i] = min(suff[i+1], a[i]);
rep(qi, q) {
int l, r;
cin >> l >> r;
--l;
int ans = min(pref[l], suff[r]);
cout << ans << '\n';
}
return 0;
}
T2. 二进制
可以直接数位dp,或者考虑组合数学的做法
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
const int M = 60;
ll dp[61][2][2][61];
void solve() {
ll n; int k;
cin >> n >> k;
n++;
rep(i, M+1)rep(j, 2)rep(s, 2)rep(p, k+1) dp[i][j][s][p] = 0;
dp[M][0][0][0] = 1;
for (int i = M-1; i >= 0; --i) {
rep(j, 2)rep(s, 2)rep(p, k+1) {
ll now = dp[i+1][j][s][p];
if (now == 0) continue;
rep(a, 2) {
int ns = s, np = p+a;
if (s == 0) {
if (a < (n>>i&1)) ns = 1;
if (a > (n>>i&1)) continue;
}
if (np > k) continue;
dp[i][j][ns][np] += now;
if (j == 0 and a) dp[i][1][ns][np] += now;
}
}
}
ll ans = dp[0][1][1][k]/k;
cout << ans << '\n';
}
int main() {
int t = 1;
while (t--) solve();
return 0;
}
T3. 斯瓦普
首先对于所有满足 \(a_i > b_i\) 的 \(i\),交换 \(a_i\) 和 \(b_i\)
考虑创建一个新序列 \(\{(a_1, b_1), (a_2, b_2), \cdots, (a_n, b_n)\}\) 并将其做升序排序,记做序列 \(c\)
然后用 std::set 来维护序列 \(a\),答案初始值就是 \(a\) 的极差
依次尝试将每个 \(a_i\) 替换成 \(b_i\) 后检验会不会令答案变小
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using P = pair<int, int>;
int main() {
int n;
cin >> n;
vector<int> a(n), b(n);
rep(i, n) cin >> a[i];
rep(i, n) cin >> b[i];
rep(i, n) {
if (a[i] > b[i]) swap(a[i], b[i]);
}
multiset<int> st;
rep(i, n) st.insert(a[i]);
int ans = *st.rbegin() - *st.begin();
vector<P> c(n);
rep(i, n) c[i] = P(a[i], b[i]);
sort(c.begin(), c.end());
rep(i, n) {
st.erase(st.find(c[i].first));
st.insert(c[i].second);
ans = min(ans, *st.rbegin() - *st.begin());
}
cout << ans << '\n';
return 0;
}
T4. 超级车流量
原题:CF1747E
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
ll x;
mint(ll x=0):x((x%mod+mod)%mod) {}
mint operator-() const {
return mint(-x);
}
mint& operator+=(const mint a) {
if ((x += a.x) >= mod) x -= mod;
return *this;
}
mint& operator-=(const mint a) {
if ((x += mod-a.x) >= mod) x -= mod;
return *this;
}
mint& operator*=(const mint a) {
(x *= a.x) %= mod;
return *this;
}
mint operator+(const mint a) const {
return mint(*this) += a;
}
mint operator-(const mint a) const {
return mint(*this) -= a;
}
mint operator*(const mint a) const {
return mint(*this) *= a;
}
mint pow(ll t) const {
if (!t) return 1;
mint a = pow(t>>1);
a *= a;
if (t&1) a *= *this;
return a;
}
// for prime mod
mint inv() const {
return pow(mod-2);
}
mint& operator/=(const mint a) {
return *this *= a.inv();
}
mint operator/(const mint a) const {
return mint(*this) /= a;
}
};
istream& operator>>(istream& is, mint& a) {
return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
return os << a.x;
}
struct modinv {
int n; vector<mint> d;
modinv(): n(2), d({0,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(-d[mod%n]*(mod/n)), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} invs;
struct modfact {
int n; vector<mint> d;
modfact(): n(2), d({1,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(d.back()*n), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} facts;
struct modfactinv {
int n; vector<mint> d;
modfactinv(): n(2), d({1,1}) {}
mint operator()(int i) {
while (n <= i) d.push_back(d.back()*invs(n)), ++n;
return d[i];
}
mint operator[](int i) const { return d[i];}
} ifacts;
mint comb(int n, int k) {
if (n < k || k < 0) return 0;
return facts(n)*ifacts(k)*ifacts(n-k);
}
int main() {
int n, m;
cin >> n >> m;
if (m > n) swap(m, n);
mint inv2 = mint(2).inv();
auto d = [&](int x) {
return mint(x+1)*inv2;
};
mint ans;
mint pw = mint(2).pow(n+m);
rep(i, m+1) {
pw *= inv2;
ans += comb(n, i)*comb(m, i)*pw*(d(n+m-i)+i+1);
}
cout << ans << '\n';
return 0;
}
浙公网安备 33010602011771号