小红的小苯题

题目链接: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;
        }
    }
}
posted @ 2025-05-15 19:20  Marinaco  阅读(24)  评论(0)    收藏  举报
//雪花飘落效果