T1:子集和(七)

考虑折半搜索
先暴力预处理出左右两部分的子集和序列 \(b\)\(c\)
并对两序列做排序
然后固定 \(c_i\),二分找到 \(b\) 序列中第一个大于 \(-c_i\) 的位置 \(j\),那么对答案的贡献就是 \(|b|-j+1\)

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;

int main() {
    int n;
    cin >> n;
    
    vector<int> a(n);
    rep(i, n) cin >> a[i];
    
    int m = n/2;
    int m2 = 1<<m;
    vector<ll> b(m2);
    rep(i, m2) {
        ll s = 0;
        rep(j, m) if (i>>j&1) s += a[j];
        b[i] = s;
    }
    sort(b.begin(), b.end());
    int k = n-m;
    vector<int> x;
    for (int i = m; i < n; ++i) x.push_back(a[i]);
    int k2 = 1<<k;
    vector<ll> c(k2);
    rep(i, k2) {
        ll s = 0;
        rep(j, k) if (i>>j&1) s += x[j];
        c[i] = s;
    }
    sort(c.begin(), c.end());
    
    ll ans = 0;
    for (int i = 0; i < k2; ++i) {
        int j = upper_bound(b.begin(), b.end(), -c[i])-b.begin();
        ans += m2-j;
    }
    
    cout << ans << '\n';
    
    return 0;
}

T2:方格路径(二)

01bfs

原题:LC2290

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;
using P = pair<int, int>;

const int di[] = {-1, 0, 1, 0};
const int dj[] = {0, 1, 0, -1};

int main() {
    int n, m;
    cin >> n >> m;
    
    vector<string> s(n);
    rep(i, n) cin >> s[i];
    
    const int INF = 1001001001;
    vector dist(n, vector<int>(m, INF));
    deque<P> q;
    dist[0][0] = 0;
    q.emplace_back(0, 0);
    while (q.size()) {
        auto [i, j] = q.front(); q.pop_front();
        int d = dist[i][j];
        rep(v, 4) {
            int ni = i+di[v], nj = j+dj[v];
            if (ni < 0 or ni >= n or nj < 0 or nj >= m) continue;
            if (dist[ni][nj] != INF) continue;
            dist[ni][nj] = d+(s[i][j] == '*');
            if (s[ni][nj] == '*') q.emplace_back(ni, nj);
            else q.emplace_front(ni, nj);
        }
    }
    
    int ans = dist[n-1][m-1]+(s[n-1][m-1] == '*');
    cout << ans << '\n';
    
    return 0;
}

T3:工程建设

拓扑排序

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using namespace std;
using ll = long long;

int main() {
    int n, m;
    cin >> n >> m;
    
    vector<int> t(n);
    rep(i, n) cin >> t[i];
    
    vector<vector<int>> to(n);
    vector<int> deg(n);
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        to[a].push_back(b);
        deg[b]++;
    }
    
    vector<ll> c(n);
    queue<int> q;
    rep(v, n) if (!deg[v]) q.push(v), c[v] = t[v];
    
    while (q.size()) {
        int v = q.front(); q.pop();
        for (int u : to[v]) {
            c[u] = max(c[u], c[v]);
            --deg[u];
            if (!deg[u]) {
                c[u] += t[u];
                q.push(u);
            }
        }
    }
    
    ll ans = 0;
    rep(i, n) ans = max(ans, c[i]);
    
    cout << ans << '\n';
    
    return 0;
}

T4:组合数的余数

组合数的定义

\( \binom{n}{m} = \frac{n \times (n-1) \times \cdots \cdots \times (n-m+1)}{m!} \)

代码实现
#include <bits/stdc++.h>

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;
}

int main() {
    int n, m;
    cin >> n >> m;
    
    mint ans = 1;
    for (int i = 0; i < m; ++i) ans *= n-i;
    for (int i = 1; i <= m; ++i) ans /= i;
    
    cout << ans << '\n';
    
    return 0;
}