CF1610D题解
前言
上一场 CF(CF1860)构造题炸了,找题做的时候发现的这题。
A 了之后看了眼题解,发现我的解法和题解不太一样。
题解
CF1800,甚至还有个 flow 的标签
文中用
第一反应肯定拆数字。
将所有的异或和拆成二进制,则题目变为求 32 个 01 矩阵,使异或和满足行和列的需求。
观察得到的 01 序列,可以发现:
如果行与列序列在这一位上的异或和不等,则一定不存在这样的矩阵,直接输出 NO;
否则只有三种可能性:
行序列和列序列上的 1 一样多,则对每一个 1 从左往右扫一遍,如果找到1就直接将矩阵中该位置变为 1
行序列上的 1 比列序列上的 1 多,则每次扫到
下标时如果没扫到 1,则直接将 变成 1 列序列上的 1 比行序列上的 1 多,则行上扫完以后将列序列中所有仍为 1 的下标
的 变成 1
如果有点懵可以自己手动做一下。
答案位移后相加即可。
code
#include <bits/stdc++.h>
using namespace std;
int n,i,j,k,m;
int a[105],b[105];
int ans[105][105];
int ansa[105],ansb[105];
int main() {
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=m;i++)
scanf("%d",&b[i]);
for(i=0;i<=30;i++){
int sum1=0,sum2=0;
for(j=1;j<=n;j++){
ansa[j]=a[j]&1;
a[j]>>=1;
sum1^=ansa[j];
}
for(j=1;j<=m;j++){
ansb[j]=b[j]&1;
b[j]>>=1;
sum2^=ansb[j];
}
if(sum1!=sum2){
printf("NO");
return 0;
}
for(j=1;j<=n;j++){
if(ansa[j]==0) continue;
else{
bool flag=false;
for(k=1;k<=m;k++){
if(ansb[k]==1){
ansb[k]=0;
ansa[j]=0;
ans[j][k]|=(1<<i);
flag=true;
break;
}
}
if(flag==false){
ansb[1]=1;
ansa[j]=0;
ans[j][1]|=(1<<i);
}
}
}
for(j=1;j<=m;j++)
if(ansb[j]==1){
ansb[j]=0;
ans[1][j]|=(1<<i);
}
}
printf("YES\n");
for(i=1;i<=n;i++){
for(j=1;j<=m;j++)
printf("%d ",ans[i][j]);
printf("\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通