Codeforces 1530F. Bingo

news/发布时间2024/5/13 0:53:29

一年一更任务达成√

题目链接:F - Bingo

题目大意:给定一个 \(n\times n(n\le 21)\) 表格,表格中每个元素有 \(p_{i,j}\) 的概率为 \(1\),否则为 \(0\)。求至少有一行或一列或一条对角线全为 \(1\) 的概率,其中对角线指两条主副对角线。

考虑一个 naive 的容斥想法,直接容斥有多少条(行/列/对角线)是不全为 \(1\) 的,并进行计算。

此时发现不全为 \(1\) 的计算很繁,于是考虑求原题的补集。即求所有(行/列/对角线)均不全为 \(1\)(或者说均存在 \(0\))的概率,那么容斥之后则是求钦定某些(行/列/对角线)均全为 \(1\) 的概率,这个概率可以非常直接地算出来:把所有被钦定为 \(1\) 的位置对应的 \(p_{i,j}\) 乘起来即可。

那么采用这种做法,复杂度则是 \(O(n^22^{2n})\) 级别的,显然无法接受。

考虑一个神奇的想法,把容斥计算拆成两部分。假设我们已经钦定了有哪些列或对角线是全为 \(1\) 的,观察下我们计算的是什么。

我们的式子本来是所有被钦定为 \(1\) 的位置的 \(p_{i,j}\) 之积,而现在在这一前提下,则变成我们要再次钦定有哪些行是全为 \(1\) 的,并计算 在第一轮钦定中变为 \(1\)\(p_{i,j}\) 之积乘上(枚举第二轮钦定哪些行全为 \(1\),并计算容斥系数乘上在第二轮钦定中新成为 \(1\)\(p_{i,j}\) 之积的和)。

而对于括号内的部分,对应式子的意义等同于求每一行均不全为 \(1\) 的概率。这时我们发现,这里的每一行相互之间是独立的,所以每行的贡献可以分开算,最后再乘起来就好。

于是我们考虑对每一行预处理在钦定了些列或对角线为 \(1\) 后,该行不全为 \(1\) 的概率。注意到钦定某些位置为一相当于修改对应的 \(p_{i,j}\) 使其变为 \(1\)。所以把对应行 \(p_{i,j}\) 的乘积直接除掉对应列集合的乘积即可,这玩意可以直接利用 lowbit 转移 \(O(2^n)\) 求出来,而对于对角线的部分直接枚举四种情况分别做就好。这样时间复杂度是 \(O(n2^n)\) 的,足以通过此题。

在实现时,可以先 \(2^2\) 枚举对角线的情况,再容斥列,这样实现起来会方便些。

#include<bits/stdc++.h>
using namespace std;
#define MOD 31607
#define N 21
int n,m,ans,a[N][N],b[N][N],f[N][1<<N],c[N],g[1<<N],k[1<<N],Lg[1<<N];
int lowbit(int x){return x&(-x);}
int sol()
{int res=0;for(int i=0;i<n;i++){f[i][0]=1;for(int j=1;j<=m;j++)f[i][j]=f[i][j^lowbit(j)]*b[i][Lg[lowbit(j)]]%MOD;for(int j=0;j<=m;j++)f[i][j]=(MOD+1-f[i][j])%MOD;}for(int j=0;j<=m;j++)for(int i=n-2;i>=0;i--)(f[i][j]*=f[i+1][j])%=MOD;for(int i=0;i<=m;i++)res=(res+f[0][m^i]*g[i]%MOD*k[i])%MOD;return res;
}
int pre(int o1,int o2)
{int K=1;for(int i=0;i<n;i++)for(int j=0;j<n;j++)b[i][j]=a[i][j];if(o1)for(int i=0;i<n;i++)(K*=b[i][i])%=MOD,b[i][i]=1;if(o2)for(int i=0;i<n;i++)(K*=b[i][n-i-1])%=MOD,b[i][n-i-1]=1;for(int i=0;i<n;i++)c[i]=1;for(int i=0;i<n;i++)for(int j=0;j<n;j++)c[j]=c[j]*b[i][j]%MOD;g[0]=1;for(int i=1;i<=m;i++)g[i]=g[i^lowbit(i)]*c[Lg[lowbit(i)]]%MOD;return K*sol()%MOD;
}
int main()
{k[0]=1;for(int i=0,o=1;i<N;i++,o<<=1)Lg[o]=i;for(int i=1;i<(1<<N);i++)k[i]=MOD-k[i^lowbit(i)];scanf("%d",&n),m=(1<<n)-1;for(int i=0;i<n;i++)for(int j=0;j<n;j++){ scanf("%d",&a[i][j]);(a[i][j]*=3973)%=MOD;}for(int i=0;i<2;i++)for(int j=0;j<2;j++)ans=(ans+(i^j?MOD-1:1)*pre(i,j))%MOD;printf("%d\n",(MOD+1-ans)%MOD);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/75277807.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

结对编程 小学四则运算

程序代码 #include<iostream> #include<vector> #include<algorithm> #include<string> #include<map> #include<stack> using namespace std; int check(int s1, int s2, int s3, char c1, char c2) {int num1;int num2;if (c2 == * || c…

四月二十五日 Android studio关于使用sqlite数据库

昨天早上六点就起来要去排队考科目一,实在是困得很,昨天晚上早早就睡了,其实解释为什么昨天没有博客。 一个好消息就是我顺利的考过了,刚到90,还是很惊险。 还是说一下最近在干什么,之前是一直用的MySQL连接我的Android studio,最近在学习使用它自带的一个sqlite数据库,…

HASHCTF2024

Secret of Keyboard 签到脚本题,有些同学的脚本解出来大小写不正确可能是由于脚本无法识别shift+字母的组合键 首先使用tshark: tshark -r usb.pcap -T fields -e usb.capdata | sed /^\s*$/d > usbdata.txt 提取数据并删除空格 然后脚本一把梭出来:keyboard.py: normalK…

用DolphinScheduler轻松实现Flume数据采集任务自动化!

转载自天地风雷水火山泽 目的 因为我们的数仓数据源是Kafka,离线数仓需要用Flume采集Kafka中的数据到HDFS中。 在实际项目中,我们不可能一直在Xshell中启动Flume任务,一是因为项目的Flume任务很多,二是一旦Xshell页面关闭Flume任务就会停止,这样非常不方便,因此必须在后台…

记一次new ArrayList导致的cpu飙升问题排查

参考:https://mp.weixin.qq.com/s/8JDPOAvmKYP8JZxau45hdw前言当时场景正常的jvm监控曲线图产生问题的jvm监控曲线图具体分析结束语昨天线上容器突然cpu飙升,也是第一次排查这种问题所以记录一下~ 前言 首先问题是这样的,周五正在写文档,突然收到了线上报警,发现cpu占用达到…

RocketMQ 之 IoT 消息解析:物联网需要什么样的消息技术?

前言: 从初代开源消息队列崛起,到 PC 互联网、移动互联网爆发式发展,再到如今 IoT、云计算、云原生引领了新的技术趋势,消息中间件的发展已经走过了 30 多个年头。 目前,消息中间件在国内许多行业的关键应用中扮演着至关重要的角色。随着数字化转型的深入,客户在使用消息…