码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ JZPLIT

时间:2019-01-14 14:43:15      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:bit   oid   prot   read   操作方法   template   操作   位置   utc   

Problem

SPOJ

Solution

考虑任意一个作为矩阵四个角的位置

\(r_i \oplus c_j\oplus a_{i,j}\oplus x_{i,j}=0\)

\(r_i \oplus c_{j+1}\oplus a_{i,j+1}\oplus x_{i,j+1}=0\)

\(r_{i+1}\oplus c_j\oplus a_{i+1,j}\oplus x_{i+1,j}=0\)

\(r_{i+1}\oplus c_{j+1}\oplus a_{i+1,j+1}\oplus x_{i+1,j+1}=0\)

\(a_{i,j}\oplus a_{i,j+1}\oplus a_{i+1,j}\oplus a_{i+1,j+1}\oplus x_{i,j}\oplus x_{i,j+1}\oplus x_{i+1,j}\oplus x_{i+1,j+1}=0\)

则只需要解出第一行第一列的操作方法就可以表示其他格子的操作方法。

未知的状态数就减少到\(O(n+m-1)\)。对于所有第一行第一列的格子列方程,即这行这列的所有操作异或后等于当前状态,然后bitset优化即可。

时间复杂度\(O(\frac {(n+m)^3} {32})\),注意卡常。

Code

#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("Ofast")
#pragma GCC optimize(3)
#include <cstdio>
#include <bitset>
using namespace std;
typedef long long ll;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
    if(ch==‘-‘) f=1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    if(f) x=-x;
}
int n,m,a[1010][1010],b[2010][2010],ans[1010][1010];
char s[1010];
bitset<2010> x[2010];
inline void calc(int i,int j,int id)
{
    b[id][1]^=1;b[id][j]^=1;b[id][i+m-1]^=1;
    b[id][n+m]^=a[1][1]^a[1][j]^a[i][1]^a[i][j];
}
void gauss()
{
    int k;
    for(int i=1;i<n+m;i++)
    {
        for(k=i;k<n+m;k++)
          if(x[k][i]) break;
        if(k>=n+m) continue;
        if(k^i) swap(x[i],x[k]);
        for(int j=1;j<n+m;j++)
          if(i^j&&x[j][i])
            x[j]^=x[i];
    }
}
int main()
{
    read(n);read(m);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=m;j++) a[i][j]=(s[j]==‘1‘);
    }
    for(int i=1;i<n+m;i++) b[i][i]=1;
    for(int i=1;i<n+m;i++) b[1][i]=1;
    b[1][n+m]=a[1][1];
    //the first eq
    for(int i=2;i<=m;i++)
    {
        b[i][n+m]=a[1][i];
        for(int j=1;j<=m;j++) b[i][j]=1;
    }
    for(int i=2;i<=n;i++)
    {
        b[i+m-1][n+m]=a[i][1];b[i+m-1][1]=1;
        for(int j=m+1;j<n+m;j++) b[i+m-1][j]=1;
    }
    for(int i=2;i<=n;i++)
      for(int j=2;j<=m;j++)
      {
        calc(i,j,j);
        calc(i,j,i+m-1);
      }
    for(int i=1;i<n+m;i++)
      for(int j=1;j<=n+m;j++)
        if(b[i][j])
          x[i].set(j);
    gauss();
    for(int i=1;i<=m;i++) ans[1][i]=x[i][n+m];
    for(int i=2;i<=n;i++) ans[i][1]=x[i+m-1][n+m];
    for(int i=1;i<=n;i++,putchar(‘\n‘))
      for(int j=1;j<=m;j++)
      {
        if(i>1&&j>1)
          ans[i][j]=a[1][1]^a[i][1]^a[1][j]^a[i][j]^ans[1][1]^ans[i][1]^ans[1][j];
        printf("%d",ans[i][j]);
      }
    return 0;
}

SPOJ JZPLIT

标签:bit   oid   prot   read   操作方法   template   操作   位置   utc   

原文地址:https://www.cnblogs.com/totorato/p/10265971.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!