zoukankan      html  css  js  c++  java
  • CF40E Number Table 题解

    Description

    洛谷传送门

    输入格式

    第 1 行两个整数 (n)(m),表示一个 (n imes m) 的矩阵。

    第 2 行一个整数 (k),表示有 (k) 个点已经被填上数。

    (3) ~ (k + 2) 行,每行 3 个整数 (a)(b)(c),表示矩阵(M_{a,b} = c)

    (k + 3) 行,1 个整数 (p),表示模数。

    输出格式

    一个整数,表示方案数。

    Solution

    我们首先考虑填一个空的矩阵有多少种方案数。

    对于 1 ~ (n - 1) 行,我们先把最后一个数单独取出来一个数,剩下前 (m - 1) 个数随便填,最后一个数可以让这一行的乘积变成 -1。

    同理,不管前 (n - 1) 行怎么填,最后一行总能让每一列的乘积变为 -1。

    所以总方案数就是:

    [ans = 2^{(n - 1)(m - 1)} ]

    下面我们来考虑一下这道题。

    首先可以判一波无解,先把结论放在这里:(n)(m) 奇偶性不同时,无解。

    证明:

    每一行,每一列乘积都为 -1,我们可以把这些 -1 乘在一起,即((-1)^{n + m}),再考虑一下这些数乘起来的本质是什么,是不是矩阵中每一个点的平方的乘积呢?是的。也就是说,乘积必为正数,就是 1。但当 (n)(m) 奇偶数性不同时,乘积是 -1,矛盾。

    证毕.

    我们继续来分析,观察到最后一句话:(0 leq k < max(n, m))

    这有什么用呢?

    我们假设 (n > m),上面的条件就变为了 (k < n),也就是说,不论你怎么填,必定有一行是空的(一个数都没有)。

    我们发现,这样就有上面简化版题目的性质了,即,我们可以不考虑列了。

    这时我们也可以套用上面的解法了,(O(n)) 枚举每一行,(ans = ans imes 2^{m - cnt_i - 1})(cnt_i) 是第 (i) 行 1 的个数,减去 1 是因为要空出来一个数来使这一行的乘积为 -1。

    注意:这里也要判一下无解,当有一行全部被填满且乘积为 1 时,无解(显然)。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1010;
    int n, m, k, mod, flag;
    int x[N], y[N], z[N];
    int line[N], mul[N], fac[N];
    
    int main(){
        scanf("%d%d%d", &n, &m, &k);
        if((n + m) & 1){
            puts("0");
            return 0;
        }
        if(n < m) swap(n, m), flag = 1;
        for(int i = 1; i <= n; ++i) mul[i] = 1;
        for(int i = 1, x, y, z; i <= k; ++i){
            scanf("%d%d%d", &x, &y, &z);
            if(flag) swap(x, y);
            line[x]++, mul[x] *= z;
        }
        scanf("%d", &mod);
        fac[0] = 1;
        for(int i = 1; i <= n; ++i)
            fac[i] = fac[i - 1] * 2 % mod;
        int ans = 1;
        for(int i = 1; i < n; ++i)
            if(!line[i]){
                swap(line[i], line[n]), swap(mul[i], mul[n]);
                break;
            }
        for(int i = 1; i < n && ans; ++i){
            if(line[i] == m && mul[i] == 1) ans = 0;
            if(line[i] < m) ans = ans * (long long)fac[m - line[i] - 1] % mod;
        }
        printf("%d
    ", ans);
        return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15496844.html

  • 相关阅读:
    Python操作SQLServer示例
    T-SQL 谓词和运算符
    T-SQL 语句—— 游标
    SQL中的循环、for循环、游标
    web自动化快速入门
    接口自动化的总结
    jenkins知识
    SVN知识
    random.sample函数
    项目实战(六)
  • 原文地址:https://www.cnblogs.com/xixike/p/15496844.html
Copyright © 2011-2022 走看看