• 省选测试31


    A coin

    题目大意 : 给出每个人喜欢每个物品的概率,问期望满意人数的最大值

    • 可以贪心的选可以增加期望最大的物品,用个堆就行

    • 设f[k][c][n]表示前i个人c个k物品的期望,增加的期望就是f[k][c][n]-f[k][c-1][n]

    • 转移的话就看这个人喜欢的是这个物品,或不是这个物品

    Code

    Show Code
    #include <queue>
    #include <vector>
    #include <cstdio>
    
    using namespace std;
    const int N = 3005, M = 305;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    int n, m, s[M];
    double p[N][M], ans;
    vector<double> f[M][N];
    priority_queue< pair<double, int> > q;
    
    double F(int k, int c, int n) {
        while (!p[n][k] && n) n--;
        if (!c || !n) return 0.0;
        if (f[k][c][n]) return f[k][c][n];
        return f[k][c][n] = (1 + F(k, c - 1, n - 1)) * p[n][k] + F(k, c, n - 1) * (1 - p[n][k]);
    }
    
    int main() {
        n = read(); m = read();
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
                p[i][j] = read() / 1000.0;
        for (int i = 1; i <= m; ++i) {
            f[i][1].resize(n + 1);
            q.push(make_pair(F(i, 1, n), i));
        }
        for (int i = 1; i <= n; ++i) {
            int x = q.top().second; ans += q.top().first;
            q.pop(); s[x]++;
            f[x][s[x]+1].resize(n + 1);
            q.push(make_pair(F(x, s[x] + 1, n) - F(x, s[x], n), x));
        }
        printf("%.10lf
    ", ans);
        return 0;
    }
    

    B B

    题目大意 : n个点的树,断k条边再脸上k条边共会出现多少种树

    • 先矩阵树定理再来个高斯消元,复杂度n4

    • 还可以容斥,复杂度n2,不过没有写

    Code

    Show Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 55, M = 998244353;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    bool v[N][N];
    int a[N][N], b[N][N], n, m, ans;
    
    int Pow(int a, int k = M - 2, int ans = 1) {
        for (; k; k >>= 1, a = 1ll * a * a % M)
            if (k & 1) ans = 1ll * ans * a % M;
        return ans;
    }
    
    int Det(int n) {
        int ans = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = i + 1; j <= n && !a[i][i]; ++j)
                if (a[j][i]) swap(a[i], a[j]), ans = M - ans;
            int inv = Pow(a[i][i]);
            for (int j = i + 1; j <= n; ++j) {
                if (!a[j][i]) continue;
                int tmp = 1ll * a[j][i] * inv % M;
                for (int k = i; k <= n; ++k)
                    if ((a[j][k] -= 1ll * a[i][k] * tmp % M) < 0) a[j][k] += M;
            }
            ans = 1ll * ans * a[i][i] % M;
        }
        return ans;
    }
    
    void Gs(int (*a)[N]) {
        for (int i = 1; i <= n; ++i) {
            for (int j = i + 1; j <= n && !a[i][i]; ++j)
                if (a[j][i]) swap(a[i], a[j]);
            int inv = Pow(a[i][i]);
            for (int j = i + 1; j <= n; ++j) {
                if (!a[j][i]) continue;
                int tmp = 1ll * a[j][i] * inv % M;
                for (int k = i; k <= n + 1; ++k)
                    if ((a[j][k] -= 1ll * a[i][k] * tmp % M) < 0) a[j][k] += M;
            }
        }
        for (int i = n; i >= 1; --i) {
            int sum = 0;
            for (int j = i + 1; j <= n; ++j)
                sum = (sum + 1ll * a[i][j] * a[j][j]) % M;
            a[i][i] = 1ll * (a[i][n+1] - sum + M) * Pow(a[i][i]) % M;
        }
    }
    
    int main() {
    #ifdef Shawk
        freopen("in", "r", stdin);
    #endif
        n = read(); m = read();
        for (int i = 2; i <= n; ++i) {
            int x = read() + 1;
            v[x][i] = v[i][x] = 1;
        }
        for (int k = 1; k <= n; ++k) {
            memset(a, 0, sizeof(a));
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= n; ++j) {
                    if (i == j) continue;
                    int x = v[i][j] ? 1 : k;
                    if ((a[i][j] -= x) < 0) a[i][j] += M;
                    if ((a[i][i] += x) >= M) a[i][i] -= M;
                }
            }
            b[k][1] = 1; b[k][n+1] = Det(n - 1);
            for (int i = 2; i <= n; ++i)
                b[k][i] = 1ll * b[k][i-1] * k % M;
            //printf("%d %d
    ", k, b[k][n+1]);
        }
        Gs(b);
        for (int i = 1; i <= m + 1; ++i)
            if ((ans += b[i][i]) >= M) ans -= M;
        printf("%d
    ", ans);
        return 0;
    }
    

    C battery

    题目大意 : 炮台可以横着摆放,也可以竖着摆放,两端都可以发射激光。图中有反射镜,问怎样摆放才能让炮台达不到炮台并且每个空地都会被激光经过

    • 很容易想到对炮台横竖摆放做2-sat,但是不好保证每个空地的都能被经过

    • 我们再考虑,每个空地在横着或竖着不可能会被两个以上的炮台经过,因为这样如果想让这个空地被激光经过,这条激光一定会打到炮台

    • 所以可以找到横竖两个方向经过空地的炮台,要求要空地必须有激光,如果炮台没有被经过,就无解;如果只被一个炮台经过,这个炮台强制选这个方向;
      如果被两个炮台经过,那一个炮台换别的方向的时候另一个就得强制在这个方向

    • 当然如果有炮台横竖都能打到炮台,也是无解

    • 接下来2-sat就行了

    Code

    Show Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 55, M = N * N * 2;
    
    struct Edge {
        int n, t;
    }e[M];
    int h[M], edc;
    
    void Add(int x, int y) {
        e[++edc] = (Edge) {h[x], y}; h[x] = edc;
    }
    
    bool g;
    char s[N][N];
    int n, m, c0, c1, id[N][N], stk[M], tp, b[M][2];
    int dfn[M], dfc, low[M], c[M], cnt, px[M], py[M];
    int dx[] = {0, 1, -1, 0}, dy[] = {1, 0, 0, -1};
    //u2,d1,l3,r0
    
    void Dfs(int x, int y, int k) {
        while(g) {
            x += dx[k], y += dy[k];
            if (s[x][y] == '-') g = 0;
            if (s[x][y] == '.') stk[++tp] = id[x][y];
            if (s[x][y] == '#' || !s[x][y]) return;
            if (s[x][y] == '\') k ^= 1;
            if (s[x][y] == '/') k ^= 2;
        }
    }
    
    void Tarjan(int x) {
        dfn[x] = low[x] = ++dfc; stk[++tp] = x;
        for (int i = h[x], y; i; i = e[i].n) {
            if (!dfn[y=e[i].t]) Tarjan(y), low[x] = min(low[x], low[y]);
            else if (!c[y]) low[x] = min(low[x], dfn[y]);
        }
        if (dfn[x] == low[x] && ++cnt) while (1) {
            c[stk[tp]] = cnt;
            if (stk[tp--] == x) break;
        }
    }
    
    void Solve() {
        scanf("%d%d", &n, &m);
        memset(s[n+1] + 1, 0, m);
        memset(b + 1, 0, c0 * 8);
        memset(c + 1, 0, c1 * 8);
        memset(h + 1, 0, c1 * 8);
        memset(dfn + 1, 0, c1 * 8);
        c0 = edc = dfc = cnt = 0; c1 = 1;
        for (int i = 1; i <= n; ++i) {
            scanf("%s", s[i] + 1);
            for (int j = 1; j <= m; ++j) {
                if (s[i][j] == '.') id[i][j] = ++c0;
                if (s[i][j] == '|') s[i][j] = '-';
            }
        }
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                if (s[i][j] != '-') continue;
                c1++, px[c1] = i; py[c1] = j;
                g = 1; Dfs(i, j, 0); Dfs(i, j, 3); bool tmp = g;
                if (!g) tp = 0;
                while (tp) (b[stk[tp]][0] ? b[stk[tp]][1] : b[stk[tp]][0]) = c1, tp--;
                c1++;
                g = 1; Dfs(i, j, 1); Dfs(i, j, 2);
                if (!g) tp = 0;
                while (tp) (b[stk[tp]][0] ? b[stk[tp]][1] : b[stk[tp]][0]) = c1, tp--;
                if (!tmp && !g) return puts("IMPOSSIBLE"), void();
                if (!tmp) Add(c1 - 1, c1);
                if (!g) Add(c1, c1 - 1);
            }
        }
        for (int i = 1; i <= c0; ++i) {
            if (b[i][0] && b[i][1]) Add(b[i][0] ^ 1, b[i][1]), Add(b[i][1] ^ 1, b[i][0]);
            else if (b[i][0]) Add(b[i][0] ^ 1, b[i][0]);
            else return puts("IMPOSSIBLE"), void();
        }
        for (int i = 2; i <= c1; ++i)
            if (!dfn[i]) Tarjan(i);
        for (int i = 2; i <= c1; i += 2) {
            if (c[i] == c[i+1]) return puts("IMPOSSIBLE"), void();
            else if (c[i] > c[i+1]) s[px[i]][py[i]] = '|';
        }
        puts("POSSIBLE");
        for (int i = 1; i <= n; ++i)
            printf("%s
    ", s[i] + 1);
    }
    
    int main() {
        int T; scanf("%d", &T);
        while (T--) Solve();
        return 0;
    }
    
  • 相关阅读:
    SqlServer相关文章
    C#字典(Dictionary)相关文章记录
    Mysql相关文章
    Rabbitmq相关文章
    C#多线程之锁相关文章
    23种设计模式相关文章
    IdentityServer4之Consent与offline_access
    .netCore mvc 在javascript中读取属性中文乱码的问题
    基于 NET5的QQ扫码登录的第三方实现(无需注册开发者)
    Windows 操作系统开启长路径支持
  • 原文地址:https://www.cnblogs.com/shawk/p/14457291.html
Copyright © 2020-2023  润新知