CF1842H Tenzing and Random Real Numbers

CF1842H


神秘的题,神必的我。

原题的条件有点不太好看,考虑把每个数的范围变为 \([-0.5, 0.5]\)

原题的要求形似 \(x_i + x_j \leq 0\),注意到这个式子是否成立只需要考虑绝对值较大的数的正负,考虑从小到大加入 \(x_i\)

实际上并不需要考虑相等的情况,因为在一个连续段上选出指定的数的概率是 \(0\)

假如绝对值大小关系已经确定了,那么每种情况下的概率是对称的,所以只要把方案数除以 \(n!2^n\) 即可。

那么直接状压,按绝对值从小到大加入元素,位运算判断这一位能否取正或者取负即可。

#include<bits/stdc++.h>
using namespace std;
const int mod = 998244353;
const int maxn = 22;
const int maxm = maxn * maxn + maxn;
using ll = long long;
inline ll Pow(ll a, ll b = mod - 2) {
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % mod;
        a = a * a % mod, b >>= 1;
    }
    return res;
}
inline constexpr ll bit(const ll &x) {return 1ll << x;}
int f[bit(maxn)];
int V[maxn], W[maxn];
int n, m;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> w >> u >> v;
        u--, v--;
        if((V[u] & bit(v)) && ((W[u] >> v) & 1) != w) {
            cout << 0;
            return 0;
        }
        V[u] |= bit(v);
        V[v] |= bit(u);
        W[u] |= bit(v) * w;
        W[v] |= bit(u) * w;
    }
    f[0] = 1;
    for(int sta = 1; sta < bit(n); sta++) {
        for(int u = 0; u < n; u++) {
            if(!(sta & bit(u))) continue;
            int bef = sta ^ bit(u);
            int x = (!(W[u] & sta));
            int y = ((V[u] & sta) == (W[u] & sta));
            f[sta] = (f[sta] + (x + y) * f[bef] % mod) % mod;
        }
    }
    int div = 1;
    for(int i = 1; i <= n; i++) div = (ll)div * i % mod;
    div = (ll)div * Pow(2, n) % mod;
    cout << (ll)f[bit(n) - 1] * Pow(div) % mod;
}
posted @ 2023-10-04 19:13  N2MENT  阅读(14)  评论(0)    收藏  举报