您的位置:首页 > 其它

[bzoj3503] [Cqoi2014]和谐矩阵

2016-03-22 13:56 351 查看
  昨晚开始写这题。。脑子像浆糊一样。中午直接重码然后就过了= =

  高斯消元解异或方程组。。

  暴力点的做法就是把每个点都当成一个未知数然后解方程。。O((nm)^3)似乎可过。。

  然后显然我们确定了第一行后,整个矩阵就可以确定下来了。

  至于快速判断是否合法。。直接递推到第m+1行,如果那一行上都是0就合法。(暴力应该也要用到这个)(原矩阵m行n列)

  每种方案都去重新递推一次的显然是傻逼QAQ。。。

  一开始先递推出,第m+1行上的每个点,与第一行中每个点的关系。。然后我们就得到了n个方程。

  最后高斯消元解一下方程就行了QAQ。把自由元当成1处理,这样就不会出现全0了(数据保证有解)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=42;
bool f[2][maxn][maxn],now,pre;
bool mp[maxn][maxn],ans[maxn][maxn];
int i,j,k,n,m;

inline void gauss(){
int i,j,k;
//    for(i=1;i<=m;puts(""),i++)for(j=1;j<=m;j++)printf(" %d",mp[i][j]);
for(i=1;i<=m;i++){
for(j=i;!mp[j][i]&&j<=m;j++);
if(j>m)continue;
if(j!=i)for(k=1;k<=m;k++)swap(mp[j][k],mp[i][k]);
for(j=1;j<=m;j++)if(j!=i&&mp[j][i])
for(k=1;k<=m;k++)mp[j][k]^=mp[i][k];
}
//    puts("");
//    for(i=1;i<=m;puts(""),i++)for(j=1;j<=m;j++)printf("%d ",mp[i][j]);puts("");
}

int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)f[0][i][i]=1;now=1;pre=0;
for(i=2;i<=n+1;i++,swap(now,pre))
for(j=1;j<=m;j++)
for(k=1;k<=m;k++)f[now][j][k]^=f[pre][j-1][k]^f[pre][j][k]^f[pre][j+1][k];
memcpy(mp,f[pre],sizeof(mp));
gauss();
for(i=m;i;i--)
if(!mp[i][i])ans[1][i]=1;else
for(j=i+1;j<=m;j++)if(mp[i][j])ans[1][i]^=ans[1][j];
for(i=1;i<=n;i++){
if(i>1)
for(j=1;j<=m;j++)ans[i][j]=ans[i-1][j]^ans[i-1][j-1]^ans[i-1][j+1]^ans[i-2][j];
for(j=1;j<m;j++)printf("%d ",ans[i][j]);printf("%d\n",ans[i][m]);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: