Educational Codeforces 173 Matrix Transformation

题目链接

https://codeforces.com/contest/2043/problem/E

思路

  • 首先这个能拆位搞非常显然,因为位运算可以对每一位进行操作,然后每位处理的话就是相当于转化成01矩阵。

  • 只要每位的01矩阵都能通过给的两个操作转化,则输出\(YES\),否则输出\(NO\)

  • 然后观察发现,如果最后用了行操作,发现这些行都是全0,如果是列操作,这些列就都是全1。

  • 然后举个例子。
    [1,0,0,1]
    [0,0,0,0]
    [1,0,0,1]
    [0,0,0,1]

  • 这个矩阵的最后操作肯定是对2行操作。

  • 然后因为(2,4)这个点会在最后一次操作被覆盖掉,所以我用列操作把第4列全变成1就变成了可以做的操作。

  • 同理此时我又发现可以4行可以进行操作,因为之后(4,4)会通过4列操作刷成1。

  • 反正就是这样一直类似拓扑的方式递推确定哪些行列可以通过操作刷出来。如果刷不出来那只能检查和原来的是不是一样。

  • 模拟这个过程,首先用两个容器,\(P_1\)里存i行 {0的个数,i},\(P_2\)里存j列 {1的个数,j}。

  • 然后分别排序从末尾开始检查。

  • \(cnt1\)表示现在确定使用行操作,需要满足的行里0的个数是多少。

  • \(cnt2\)表示现在确定使用行操作,需要满足的列里1的个数是多少。

  • 一开始\(cnt1\)\(m\)\(cnt2\)\(n\)。假设第一次检查发现满足0个数等于\(cnt1\)的行是\(x\)行。

  • 把这些行打上标记,从末尾弹出,之后\(cnt2\)就变成\(cnt2-x\)

  • 然后再检查有没有等于\(cnt2\)的列,假设是\(y\)列。

  • 把这些列打上标记,从末尾弹出,之后\(cnt1\)就变成\(cnt1-y\)

  • 一直做到做不了为止。

  • 检查未标记行列的两个01矩阵是否含有相同元素即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int s[N][N];
int t[N][N];
int a[N][N];
int b[N][N];
bool vis1[N];
bool vis2[N];
vector<array<int,2>>p1(N);
vector<array<int,2>>p2(N);
void solve(){
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>s[i][j];
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>t[i][j];
    for(int k=29;k>=0;k--){
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
            if((s[i][j]>>k)&1)a[i][j]=1;
            else a[i][j]=0;
            if((t[i][j]>>k)&1)b[i][j]=1;
            else b[i][j]=0;
        }
        fill(vis1,vis1+n+1,0);fill(vis2,vis2+m+1,0);
        for(int i=1;i<=n;i++){
            int x=0;
            for(int j=1;j<=m;j++){
                x+=b[i][j]==0;
            }p1[i]={x,i};    
        }
        for(int j=1;j<=m;j++){
            int x=0;
            for(int i=1;i<=n;i++){
                x+=b[i][j]==1;
            }p2[j]={x,j};
        }
        sort(p1.begin(),p1.begin()+n+1);
        sort(p2.begin(),p2.begin()+m+1);
        int A=n;int B=m;
        int cnt1=m;int cnt2=n;
        int cnt=0;
        while(A||B){
            int flag=0;
            if(A&&p1[A][0]==cnt1){
                 while(A&&p1[A][0]==cnt1){
                    flag++;vis1[p1[A--][1]]=1;
                }
                cnt2-=flag;
            }else if(B&&p2[B][0]==cnt2){
                while(B&&p2[B][0]==cnt2){
                    flag++;vis2[p2[B--][1]]=1;
                }
                cnt1-=flag;
            }
            if(!flag)break;
        }
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
            if(vis1[i]||vis2[j])continue;
            else if(a[i][j]!=b[i][j]){
                cout<<"NO"<<'\n';return;
            }
        }
    }
    cout<<"YES"<<'\n';
}
signed main(){
#ifdef ONLINE_JUDGE
#else
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
#endif
    ios::sync_with_stdio(false);cin.tie(0);
    int T;cin>>T;
    while(T--){
        solve();
    }
}
posted @ 2025-06-10 22:30  cbbdhz  阅读(15)  评论(0)    收藏  举报