ACM2022河南省赛:G. Mocha 上大班啦

843 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

ACM2022河南省赛:G. Mocha 上大班啦

G. Mocha 上大班啦

在旭丘幼儿园大班的数学课上,Mocha 学到了位运算和概率。

她认为自己已经熟练地掌握了这两个知识点,于是她找到了同学 Arisa 来出题考考自己。

Arisa 给了 Mocha n 个长度为 m 且只包含 0 和 1 的数字串,Arisa 会对这些数字串操作 q 次。每次 Arisa 会选择两个数字串 si 和 sj,并选择两个位置 l, r,对于所有的 x ∈ [l, r],将 sj [x] 替换为 sj [x] & si [x], sj [x] 为第 j 个数字串的第 x 位,其中 & 为位运算中的与运算。

但是对于第 i 次操作,只有 pi/100 的概率成功。

Arisa 想让 Mocha 计算出 q 次操作后,n 个数字串按. 位. 与. 运. 算. 后. 得到的数字串中 1 的个数的期望对 998244353 取模的结果。

Mocha 并不能解决这道问题,但是她不想丢面子,于是她想请聪明的你帮她计算出这道题的答案。

输入

第一行两个整数 n, m(2 ≤ n ≤ 1000, 1 ≤ m ≤ 4000),代表数字串的个数和长度。

之后 n 行每行一个长度为 m 且只包含 0 和 1 的数字串。

第 n + 2 行包含一个整数 q(1 ≤ q ≤ 2 × 10^5),代表操作次数。

之后 q 行,每行五个整数 i, j, l, r, p(1 ≤ i, j ≤ n, 1 ≤ l ≤ r ≤ m, 0 ≤ p ≤ 100),代表操作两个数字串的编号,操作的位置范围以及成功概率。

保证 i ̸= j。

输出

输出一个整数,代表所求期望对 998244353 取模的结果。令 M = 998 244 353,可以证明所求期望可写作既约分数 p q 的形式,其中 p, q 为整数且 q ̸≡ 0 (mod M)。输出的整数应与 p · q −1 mod M 相等,换言之,输出一个整数 x 满足 0 ≤ x < M 且 x · q ≡ p (mod M)。

样例

输入
3 3
100
110
111
1
1 2 1 2 0
​
输出
1

问题解析

大诈骗题。

重点就在于加粗的那个按. 位. 与. 运. 算. ,众所周知,按位与运算的特点是:两边都为真才是真,一方有假则是假。

对于按位与运算来说,二进制上1的个数只可能是不变或者减少,不可能增多(做不到把0变成1).所以对于每次操作来说,成不成功无所谓的,因为我们最后还有一次总的按位与运算,对于第i个位置,只要有一个字符串的第i个位置是0,那么运算完后这个位置只可能是0;只有全是1了,最后这个位置才是1,而如果全部的字符串这个位置都是1了,操作成功/失败与否都不会变化。

所以这一题就是一个诈骗题,我们只要记录每个位置上1的出现次数,记录出现次数为n的1,并把个数输出即可。

(题目要输出的是个数1的期望个数,而1的期望个数是固定的,所以我们就把记录的个数输出就好)

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
​
void solve()
{
    int n, m;
    string s;
    cin >> n >> m;
    unordered_map<int, int>mymap;
    for (int i = 1; i <= n; i++)
    {
        cin >> s;
        for (int j = 1; j <= m; j++)
        {
            if (s[j - 1] == '1')mymap[j]++;
        }
    }
    int cnt = 0;
    for (auto& i : mymap)
    {
        if (i.second == n)cnt++;
    }
    cout << cnt;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}