CF1530F Bingo
题解
容斥
- 问至少 1 行/列/对角线 全为 1 的概率
- 转化为求每 行/列/对角线 至少有 1 个 0 的概率
- 总概率 1 减去他就是答案
- 每行的状态相互独立
- 考虑枚举列和对角线的状态,0 表示存在 0,1 表示全是 1
- 根据列和对角线能推出每一行的状态
- 每一行的状态乘积就是当前 列/对角线 的状态的方案数
- 对于 列/对角线的状态
- 减去有奇数个 1 的,加上有偶数个 1 的
代码
# include <bits/stdc++.h> # define int long long using namespace std; const int MOD = 31607; const int N = (int)2e6 + 10; int n, temp; int f[22][1 << 21]; int ans; int Q_pow(int a, int b){ int ans = 1, p = a; while(b){ if(b & 1){ ans = (ans * p) % MOD; } p = (p * p) % MOD; b >>= 1; } return ans; } int lowbit(int x){ return x & (-x); } signed main(){ cin >> n; int up = (1 << n) - 1, base = Q_pow(10000ll, MOD - 2); for(int i = 1; i <= n; i++){ f[i][0] = 1; for(int j = 1; j <= n; j++){ cin >> temp; temp = temp * base % MOD; f[i][1 << (j - 1)] = temp; } for(int j = 1; j <= up; j++){ f[i][j] = f[i][j ^ lowbit(j)] * f[i][lowbit(j)] % MOD; // 状压这一行对应的列的状态 } } int upp = (1 << 2) - 1; for(int i = 0; i <= upp; i++){ for(int j = 0; j <= up; j++){ int cnt = __builtin_popcount(i) + __builtin_popcount(j); int num = 0; // 容斥系数 if(cnt % 2){ num = -1; }else{ num = 1; } for(int k = 1; k <= n; k++){ int a = j; // 列的状态 int b = (i & 1) * (1 << (k - 1)); // 对角线 1 在 第 i 行对应的状态 int c = ((i >> 1) & 1) * (1 << (n - k)); // 对角线 2 在 第 i 行对应的状态 int d = a | b | c; num = num * (f[k][d] - f[k][up] + MOD) % MOD; } ans = (ans + num) % MOD; } } ans = (1 - ans + MOD) % MOD; cout << ans << "\n"; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话