[CF1672G]Cross Xor
G - Cross Xor
对于\((n\&1)\&\&(m\&1)\)的情况,所有行、列的异或和的必须相等(异或和指当前行/列中所有元素的异或和)
每次修改的点\((x_1,y_1)\),\((x_2,y_1)\),\((x_1,y_2)\),\((x_2,y_2)\)使得所有行和列的异或和不会改变
只对\((i,j)\)进行一次操作,那么所有行和列的异或和都会改变
对于\(n\)和\(m\)一奇一偶同理,此时只需要行(\(m\&1\))或者列(\(n\&1\))的异或和相等
然后对于\((n\&1)\&\&(m\&1)\)的解法:
将每一行每一列看作一个点,有\(?\)就连接着两个点,那么对于生成的图,考虑随便找出一棵生成树,那么我们的目的就是让所有点的权值(即其对应的异或和)相等,我们钦定所有点的权值为\(x(x=0/1)\),若当前点的权值不为\(x\),那么将其连向父亲的边的权值改成\(1\),这样这个点与其父亲的权值都要\(xor\ 1\),那么无论生成树外的边如何选择,生成树上的边总有唯一一种选择使得合法,所以答案是 \(2^{边数−点数+1}\),对每个连通块分别做一次即可
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e3+5,MOD=998244353;
int n,m,a[N][N],cnt_all;
int val[N<<1],vval[N<<1],c[N][N],cnt2[N];
int dp[2],prod[2];
vector<int> edge[N<<1];
int power(int x,int y){
int ans=1;
for(;y;y>>=1,x=1ll*x*x%MOD) if(y&1) ans=1ll*ans*x%MOD;
return ans;
}
int add(int x,int y){ x+=y; if(x>=MOD) x-=MOD; return x; }
void ad(int &x,int y){ x+=y; if(x>=MOD) x-=MOD; }
int now,num_edge,num_point;
bool flag,vis[N<<1];
void dfs(int u,int fa){
vis[u]=true,++num_point;
for(auto v:edge[u]){
++num_edge;
if(!vis[v]) dfs(v,u);
if(flag) return;
}
if(val[u]^now){
if(!fa) return flag=true,void();
val[u]^=1,val[fa]^=1;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
getchar();
for(int j=1;j<=m;++j) a[i][j]=min(getchar()-'0',2),cnt_all+=(a[i][j]==2);
}
if(!(n&1)&&!(m&1)) return printf("%d",power(2,cnt_all)),0;
if((n&1)&&!(m&1)){
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
if(a[i][j]<2) val[j]^=a[i][j];
else ++cnt2[j];
}
for(int i=0;i<=max(n,m);++i){
c[i][0]=1;
for(int j=1;j<=i;++j) c[i][j]=add(c[i-1][j],c[i-1][j-1]);
}
prod[0]=prod[1]=1;
for(int i=1;i<=m;++i){
dp[0]=dp[1]=0;
for(int j=0;j<=cnt2[i];++j) ad(dp[val[i]^(j&1)],c[cnt2[i]][j]);
prod[0]=1ll*prod[0]*dp[0]%MOD,prod[1]=1ll*prod[1]*dp[1]%MOD;
}
return printf("%d",add(prod[0],prod[1])),0;
}
if(!(n&1)&&(m&1)){
for(int i=0;i<=n;++i)
for(int j=1;j<=m;++j){
if(a[i][j]<2) val[i]^=a[i][j];
else ++cnt2[i];
}
for(int i=0;i<=max(n,m);++i){
c[i][0]=1;
for(int j=1;j<=i;++j) c[i][j]=add(c[i-1][j],c[i-1][j-1]);
}
prod[0]=prod[1]=1;
for(int i=1;i<=n;++i){
dp[0]=dp[1]=0;
for(int j=0;j<=cnt2[i];++j) ad(dp[val[i]^(j&1)],c[cnt2[i]][j]);
prod[0]=1ll*prod[0]*dp[0]%MOD,prod[1]=1ll*prod[1]*dp[1]%MOD;
}
return printf("%d",add(prod[0],prod[1])),0;
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
if(a[i][j]<2) val[i]^=a[i][j],val[j+n]^=a[i][j],vval[i]=val[i],vval[j+n]=val[j+n];
else edge[i].pb(j+n),edge[j+n].pb(i);
}
int prod=1,ans=0;
for(int i=1;i<=n+m;++i)
if(!vis[i]){
flag=num_edge=num_point=0,dfs(i,0);
if(flag){ prod=0; break; }
num_edge/=2,prod=1ll*prod*power(2,num_edge-num_point+1)%MOD;
}
ad(ans,prod);
prod=now=1; for(int i=1;i<=n+m;++i) val[i]=vval[i],vis[i]=false;
for(int i=1;i<=n+m;++i)
if(!vis[i]){
flag=num_edge=num_point=0,dfs(i,0);
if(flag){ prod=0; break; }
num_edge/=2,prod=1ll*prod*power(2,num_edge-num_point+1)%MOD;
}
printf("%d",add(ans,prod));
return 0;
}
[CF1672G]Cross Xor的更多相关文章
- SQL Server 2008 R2——CROSS APPLY 根据数据出现的次数和时间来给新字段赋值
=================================版权声明================================= 版权声明:原创文章 禁止转载 请通过右侧公告中的“联系邮 ...
- 题解-CF617E XOR and Favorite Number
题面 CF617E XOR and Favorite Number 给定 \(n,m,k\) 和 \(n\) 个数的序列 \(a_i\),\(m\) 次求区间 \([l,r]\) 中异或值为 \(k\ ...
- [LeetCode] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字
Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...
- CROSS APPLY应用实例
--功能说明:统计每个人的平均分数,新字段[AVG_Score]根据PersonID链接到原表[tbiz_AssScore]上 SELECT [ID] ,[ProjectID] ,[PersonID] ...
- Domino----The Address Book does not contain a cross certificate capable of validating the public key.
The Address Book does not contain a cross certificate capable of validating the public key. 地址本不包含交叉 ...
- 二分+DP+Trie HDOJ 5715 XOR 游戏
题目链接 XOR 游戏 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- SQL Server中CROSS APPLY和OUTER APPLY的应用详解
SQL Server数据库操作中,在2005以上的版本新增加了一个APPLY表运算符的功能.新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表达式都可以, ...
- 交叉验证(Cross Validation)原理小结
交叉验证是在机器学习建立模型和验证模型参数时常用的办法.交叉验证,顾名思义,就是重复的使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏. ...
- T-SQL CROSS APPLY、MERGE
写在前面 刚才看项目里一个存储过程,也是好长时间没有使用Sql Server2008了,好多写法和函数感觉到陌生,这就遇到了CROSS APPLY 和MERGE的语法,两者之前完全没接触过. 所以专门 ...
- BZOJ 2115 【Wc2011】 Xor
Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 ...
随机推荐
- 【C语言】转义字符及其对应英文
对于很多人来说,用转义字符都是熟能生巧,而不清楚为什么是那样的转义字符,所以我在这列了一个表,翻译了其对应的英文. 转义字符分为一般转义字符.八进制转义字符.十六进制转义字符. 一般转义字符:\0. ...
- 【Markdown】公式指导手册
点击跳转至 Cmd Markdown 简明语法手册 ,立刻开始 Cmd Markdown 编辑阅读器的记录和写作之旅! 本文为 MathJax 在 Cmd Markdown 环境下的语法指引. Cmd ...
- 《机器人SLAM导航核心技术与实战》第1季:第9章_视觉SLAM系统
<机器人SLAM导航核心技术与实战>第1季:第9章_视觉SLAM系统 视频讲解 [第1季]9.第9章_视觉SLAM系统-视频讲解 [第1季]9.1.第9章_视觉SLAM系统_ORB-SLA ...
- RocketMQ的Consumer是如何消费消息的
Rocketmq提供了两种主要的消费模式:推送式消费(Push Consumer)和 拉取式消费(Pull Consumer) 一.Consumer消费消息的基本流程 1.实例化Consumer:创建 ...
- Linux之用户和用户组管理
概念 Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须要拥有一个账号进入系统,账号实质上就是一个用户在系统上的标识.系统根据标识分配不同的权限和资源.一个账号包含用 ...
- crypto14解题思路
crypto14解题思路 ##二进制 001100110011001100100000001101000011010100100000001101010011000000100000001100100 ...
- cmd /k 解决cmd命令闪退问题
cmd /k 的含义是执行后面的命令,并且执行完毕后保留窗口. & 是连接多条命令.PAUSE 表示运行结束后暂停,等待一个任意按键.EXIT 表示关闭命令行窗口.如果使用 cmd /c 就可 ...
- 想让鸿蒙应用快的“飞起”,来HarmonyOS开发者官网“最佳实践-性能专区”
在鸿蒙应用开发过程中,应用侧流畅运行体验是开发者非常关注的部分.为此,华为HarmonyOS开发者官网推出了"最佳实践-性能专区"(以下简称"性能专区"),通过 ...
- Docker自定义镜像输出日志
概述 本文主要解决Docker自定义镜像之后,通过docker logs命令查看不到相关日志的问题 在 Docker 中自定义镜像输出日志,通常需要确保你的应用程序将日志输出到 标准输出(stdout ...
- 代码随想录第十六天 | Leecode 513. 找树左下角的值、112. 路径总和、113. 路径总和 II、106. 从中序与后序遍历序列构造二叉树
Leecode 513. 找树左下角的值 题目描述 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值. 假设二叉树中至少有一个节点. 示例 1: 输入: root = [ ...