zoukankan      html  css  js  c++  java
  • 2019.10.8 模拟赛

    I don't like Matrix

    T1 I liked Matrix

    (n*m) 的矩阵A中所有位置中随机填入0或1,概率比为 (x:y) ,令 (B_i=sumlimits_{j=1}^{m}A_{i,j}) ,求 (min(B_i)) 的期望,将期望乘 ((x+y)^{nm}) 后模 (1000000007) 的值

    导公式开始:(官方题解)

    [E = sumlimits_{i = 1}^{m}i*P(min{B_i}= i) = sumlimits_{i = 1}^{m}P(min{B_i} geq i) $$ $$=sumlimits_{i = 1}^{m}P(B_i geq i)^n = sumlimits_{i = 1}^{m}(sumlimits_{j = i}^{m}P(B_i = j))^n $$ $$=sumlimits_{i = 1}^{m}(sumlimits_{j = i}^{m} frac{C_{m}^{j} * x^{m - j} * y ^ j}{(x + y)^m} )^n ]

    [ans = sumlimits_{i = 1}^{m}(sumlimits_{j = i}^{m}C_m^j * x^{m - j} * y ^ j)^n ]

    //节省空间以后放代码片段
    const int MAXM = 2e5 + 5;
    const int MOD = 1e9 + 7;
    int jx[MAXM] = {1}, jy[MAXM] = {1};
    int jc[MAXM] = {1}, jc_inv[MAXM];
    int a[MAXM];
    int n, m, x, y;
    int main()
    {
        poread(n), poread(m), poread(x), poread(y);
        for (register int i = 1; i <= m; ++i)
            jx[i] = (long long)jx[i - 1] * x % MOD;
        for (register int j = 1; j <= m; ++j)
            jy[j] = (long long)jy[j - 1] * y % MOD;
        for (register int i = 1; i <= m; ++i)
            jc[i] = (long long)jc[i - 1] * i % MOD;
        jc_inv[m] = qpow(jc[m], MOD - 2);
        for (register int i = m; i; --i)
            jc_inv[i - 1] = (long long)jc_inv[i] * i % MOD;
        for (register int i = 1; i <= m; ++i)
            jc[i] = (long long)jc[m] * jc_inv[i] % MOD * jc_inv[m - i] % MOD;
        for (register int i = m; i >= 1; --i)
            a[i] = (a[i + 1] + (long long)jc[i] * jx[m - i] % MOD * jy[i] % MOD) % MOD;
        static int ans;
        for (register int i = 1; i <= m; ++i)
            ans = (ans + qpow(a[i], n)) % MOD;
        cout << ans << endl;
    }
    

    T2 I like Matrix

    (n*m) 的零矩阵A进行Q次操作:
    (1 i j) :将 (A_{i,j}) 取反 ((xor 1))
    (2 i) :将 (A) 矩阵第 (i) 行的所有元素取反
    (3 j) :将 (A) 矩阵第 (j) 列的所有元素取反
    (4 k) :将 (A) 矩阵还原成第 (k) 次操作之后的状态
    上来就考虑可持久化?数据结构学傻的我。
    我们发现所有的操作构成了一棵树。
    所以直接按照操作顺序建树并dfs时进行计算就可以了。由于是异或操作所以异或还会变回去,一遍dfs统计答案即可。

    const int MAXQ = 1e5 + 1;
    const int MAXN = 1e3 + 1;
    short n, m;
    int q;
    struct nde
    {
        short opt, i, j;
    } que[MAXQ];
    int Ans[MAXQ];
    bool b[MAXN][MAXN];
    int ans;
    inline void change(const int &t)
    {
        short int tx = que[t].i, ty = que[t].j;
        if (que[t].opt == 1)
        {
            ans += b[tx][ty] ? -1 : 1;
            b[tx][ty] = b[tx][ty] ^ 1;
            return;
        }
        else if (que[t].opt == 2)
        {
            for (register int j = 1; j <= m; ++j)
            {
                ans += b[tx][j] ? -1 : 1;
                b[tx][j] = b[tx][j] ^ 1;
            }
            return;
        }
        else if (que[t].opt == 3)
        {
            for (register int j = 1; j <= n; ++j)
            {
                ans += b[j][tx] ? -1 : 1;
                b[j][tx] = b[j][tx] ^ 1;
            }
            return;
        }
    }
    struct Ro
    {
        int nxt, ver;
    } e[MAXQ];
    int head[MAXQ], tot = 0;
    inline void add(const int &x, const int &y)
    {
        e[++tot].ver = y;
        e[tot].nxt = head[x];
        head[x] = tot;
    }
    inline void dfs(int x)
    {
        change(x);
        Ans[x] = ans;
        for (register int i = head[x]; i; i = e[i].nxt)
            dfs(e[i].ver);
        change(x);
    }
    int main()
    {
        poread(n), poread(m), poread(q);
        for (register int i = 1; i <= q; ++i)
        {
            poread(que[i].opt);
            if (que[i].opt == 4)
            {
                register int x;
                poread(x);
                add(x, i);
                continue;
            }
            poread(que[i].i);
            if (que[i].opt == 1)
                poread(que[i].j);
            add(i - 1, i);
        }
        for (register int i = head[0]; i; i = e[i].nxt)
            dfs(e[i].ver);
        for (register int i = 1; i <= q; ++i)
        {
            printf("%d", Ans[i]);
            putchar('
    ');
        }
    }
    

    T3 I will like Matrix

    (1)(n*m) 之间的所有整数分别填入一个 (n*m) 的矩阵中,并要求其中的 (k) 个元素为局部极小值,即该元素小于周围的八个元素(如果存在),其他元素不做要求。求一共有多少种不同的矩阵,并将答案对 (1e9+7) 取模。保证一定存在合法的矩阵。

    状态压缩DP计数。
    (暴力计算s状态还有几个点能放数字g[s])
    f[i][s] 表示放了第i小的数字,当前覆盖状态为s的方案数。
    转移:
    f[i+1][s∣(2 j−1 )]+=f[i][s]
    f[i+1][s]+=f[i][s]∗(g[s]−i+cnt)

    struct node
    {
        int x, y;
    } poi[MAXK];
    int f[MAXK << 3][1 << MAXK];
    int cnt[1 << MAXK];
    int g[1 << MAXK];
    int jc[10001] = {1}, jc_inv[10001] = {1};
    bool vis[MAXN][MAXN], check[MAXN][MAXN];
    int tot;
    signed main()
    {
        poread(n), poread(m), poread(k);
        for (register int i = 1; i <= n * m; ++i)
            jc[i] = (long long)jc[i - 1] * i % MOD;
        jc_inv[n * m] = qpow(jc[n * m], MOD - 2);
        for (register int i = n * m; i; --i)
            jc_inv[i - 1] = (long long)jc_inv[i] * i % MOD;
        for (register int i = 0; i < k; ++i)
        {
            poread(poi[i].x), poread(poi[i].y);
            check[poi[i].x][poi[i].y] = true;
        }
        for (register int i = 0; i < k; ++i)
        {
            for (register int xi = max(1, poi[i].x - 1); xi <= min(n, poi[i].x + 1); ++xi)
            {
                for (register int yi = max(1, poi[i].y - 1); yi <= min(m, poi[i].y + 1); ++yi)
                {
                    if (vis[xi][yi] || check[xi][yi])
                        continue;
                    vis[xi][yi] = true;
                    ++tot;
                }
            }
        }
        for (register int s = 0; s < (1 << k); ++s)
        {
            memset(vis, 0, sizeof(vis));
            register int cnt = 0;
            for (register int i = 0; i < k; ++i)
            {
                if (s & (1 << i))
                    continue;
                for (register int xi = max(1, poi[i].x - 1); xi <= min(n, poi[i].x + 1); ++xi)
                {
                    for (register int yi = max(1, poi[i].y - 1); yi <= min(m, poi[i].y + 1); ++yi)
                    {
                        if (vis[xi][yi] || check[xi][yi])
                            continue;
                        vis[xi][yi] = true;
                        ++cnt;
                    }
                }
            }
            g[s] = tot - cnt;
        }
        f[0][0] = 1;
        for (register int i = 0; i < tot + k; ++i)
        {
            for (register int s = 0; s < (1 << k); ++s)
            {
                register int cnt = 0;
                for (register int j = 0; j < k; ++j)
                {
                    if (s & (1 << j))
                        continue;
                    f[i + 1][s | (1 << j)] = (1ll * f[i + 1][s | (1 << j)] + f[i][s]) % MOD;
                    ++cnt;
                }
                cnt = k - cnt;
                if (g[s] - i + cnt > 0)
                    f[i + 1][s] = 1ll * (f[i + 1][s] + (f[i][s] * ((g[s] - i + cnt + MOD) % MOD) % MOD)) % MOD;
            }
        }
        printf("%d
    ", 1ll * f[tot + k][(1 << k) - 1] * jc[n * m] % MOD * jc_inv[tot + k] % MOD);
        return 0;
    }
    
    晚上赶时间写的博客可能出锅

    部分内容来自nofind的博客

  • 相关阅读:
    koa2环境搭建
    单例模式
    nodejs fs path
    path node
    webpack code splitting
    babel 插件编写
    C#验证码类
    C#身份证识别相关技术
    C# Socket服务端与客户端通信(包含大文件的断点传输)
    动态抓取网页信息
  • 原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11651577.html
Copyright © 2011-2022 走看看