小红的小苯题
题目链接:https://ac.nowcoder.com/acm/contest/108589/F
题意:
构造一个nxm的矩阵,使得能用每一行的异或和值和每一列的异或和值 构造一个1~n+m的排列
思路:
当把每一行的异或和和每一列的异或和全部异或起来,可以得到值为0
因为每一个值都被行选中一次,被列选中一次,两次异或为0
即1^2^3....^n+m=0,是能构造出合法矩阵的必要条件
不妨先构造每一列的矩阵值
若令每一列的异或和值分别为1,2....m
那么可以使1,2,3..n+m独占一列,一列中其他值为0即可
然后让每一行的异或和值分别为m+1,......n+m
可以得到g[n][m]的两个异或表达式
可以看出如果两个异或表达式相等,那么1^2^...n+m=0
因此推出1^2^...n+m=0为能构造出合法矩阵的充要条件
(PS:不知道为啥下面代码sum不初始化为0就ac不了....,所以说为什么呢..)
void solve(){
int n,m;cin>>n>>m;
int a=1;
for(int i=2;i<=n+m;i++){
a^=i;
}
if(a!=0){
cout<<-1<<endl;return;
}
int f=0;
if(n>m){
f=1;
swap(n,m);
}
int p=1;
int cnt=1;
for(int i=1;i<=m-1;i++){
g[p][i]=cnt++;
p++;
p=min(p,n);
}
int compar=0;
for(int j=1;j<=m;j++){
compar^=g[n][j];
}
compar^=(n+m);
int temp=cnt;
cnt+=1;
int sum=0;
for(int i=1;i<=n-1;i++){
g[i][m]=(i^cnt);cnt++;
if(i==1)sum=g[i][m];
else{
sum^=g[i][m];
}
}
g[n][m]=temp^sum;
if(g[n][m]!=compar){
cout<<-1<<endl;return;
}
if(f){
for(int j=1;j<=m;j++){
for(int i=n;i>=1;i--){
cout<<g[i][j]<<' ';
}
cout<<endl;
}
}else{
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<g[i][j]<<' ';
}
cout<<endl;
}
}
}

浙公网安备 33010602011771号