• Codeforces 40E Number Table


    题目传送门

      传送门I

      传送门II

    题目大意

      给定一个$n imes m$的网格,每个格子上要么填$1$,要么填$-1$,有$k$个位置上的数是已经填好的,其他位置都是空的。问有多少种填法使得任意一行或一列上的数的乘积为$-1$.

      $1 leqslant n, m leqslant 10^{3}$,$1 leqslant k < max (n, m)$。

      $k$的范围醒目。那么意味着至少存在一行或者一列为空。

      假设空的是一行。那么剩下的行只需要满足那一行的乘积为$-1$,而空的这一行对应一种唯一的填法。

      可以计算出,空行补数后的乘积为$(-1)^{m} imes (-1)^{n - 1}$,即$(-1)^{m + n - 1}$。

      所以特判$m. n$奇偶性不同的时候无解。然后就可以将每一行单独计算。

      每一行中,要么只填奇数个$-1$,要么只填偶数个$-1$。这样就可以$O(nm)$的时间内解决这道题目。

      但是这不能满足装逼爱好者的欲望。明明这东西可以做到O(n)。

    定理1 当$n > 0$时,满足$sum_{k = 0}^{n}[2 mid k]C_{n}^{k} = sum_{k = 0} ^{n}[2 mid k]C_{n}^{k} = 2^{n - 1}$。

      证明 当$n$为奇数时,根据式子$C_{n}^{k} = C_{n}^{n - k}$易证。

      当$n$为偶数时,根据杨辉恒等式$C_{n}^{k} = C_{n - 1}^{k - 1} + C_{n - 1}^{k}$可得偶数位的和等于第$n - 1$层的和。

      根据杨辉三角的性质,我们知道第$n - 1$层的和是$2^{n - 1}$,第$n$层的和是$2^{n}$。

      所以第$n$层奇数位的和是$2^{n} - 2^{n - 1} = 2^{n - 1}$。

      因此定理得证。

      然后预处理2的幂,就可以做到$O(n)$了。

      (另外提一句,即使没有 $k$ 那个限制,可以做到 $O(n + k)$)

    Code

     1 /**
     2  * Codeforces
     3  * Problem#40E
     4  * Accepted
     5  * Time: 60ms
     6  * Memory: 2160k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 
    12 const int N = 1005;
    13 
    14 int n, m, k, p;
    15 boolean aflag;
    16 int pow2[N];
    17 int cnt[N], pro[N];
    18 
    19 inline void init() {
    20     scanf("%d%d", &n, &m);
    21     scanf("%d", &k);
    22     if (n < m)    swap(n, m), aflag = true;
    23     fill(pro + 1, pro + n + 1, 1);
    24     for (int i = 1, u, v, x; i <= k; i++) {
    25         scanf("%d%d%d", &u, &v, &x);
    26         if (aflag)    swap(u, v);
    27         cnt[u]++, pro[u] *= x;
    28     }
    29     scanf("%d", &p);
    30 }
    31 
    32 inline void solve() {
    33     if ((n & 1) != (m & 1)) {
    34         puts("0");
    35         return;
    36     }
    37     
    38     pow2[0] = 1;
    39     for (int i = 1; i <= n; i++)
    40         pow2[i] = (pow2[i - 1] << 1) % p;
    41     
    42     for (int i = 1; i < n; i++)
    43         if (!cnt[i]) {
    44             swap(cnt[i], cnt[n]);
    45             swap(pro[i], pro[n]);
    46             break;
    47         }
    48         
    49     int ans = 1;
    50     for (int i = 1; i < n && ans; i++) {
    51         if (cnt[i] == m) {
    52             if (pro[i] == 1)
    53                 ans = 0;
    54         } else
    55             ans = ans * 1ll * pow2[m - cnt[i] - 1] % p;
    56     }
    57     printf("%d
    ", ans);
    58 }
    59 
    60 int main() {
    61     init();
    62     solve();
    63     return 0;
    64 }
  • 相关阅读:
    自定义promise的实现
    数据双向邦定1
    上线遇到的bug
    UEGrids.js
    staticFileServer.js
    Promise
    响应式布局实例
    悬浮框的兼容性
    Fiddler Web Debugger
    js根据当前日期提前N天或推后N天的方法
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8526308.html
Copyright © 2020-2023  润新知