欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ2303


题意概括

  现在有一个N*M矩阵,矩阵上只能填数字0或1 
现在矩阵里已经有一些格子被填写了数字,询问是否存在一种填写方案使得「任意一个2*2的矩阵异或和为1」,输出方案总数


题解

  我们发现当我们已经确定(1,1)的颜色为1的时候:

  我们知道c(i,j)。

  那么如果i和j都是偶数,那么就有c(1,1)^c(i,1)^c(1,j)^c(i,j)==1

  否则就是0。

  因为假设s(i,j)表示以i,j为左上角的2*2矩阵异或起来,那么:

  S(1,1)^S(1,2)^...^S(1,j)^S(2,1)^S(2,2)^...^S(i-1,j-1)=c(1,1)^c(i,1)^c(1,j)^c(i,j)。

  而左式就等于(i-1)*(j-1)个1异或。

  这是一个好东西。

  然后我们枚举(1,1)的颜色,然后对于每一个C(i,j)就可以得到一组C(i,1)和C(1,j)的关系。

  但是当i=1或者j=1的时候,是得到一个C(i,1)或者C(1,j)的答案。

  最后得到关系之后,只需要看看是否矛盾。

  然后统计连通块数,就是自由元的总数,每一个自由元有2种取值,于是答案显而易见。

  注意输入有i=j=1的情况要特判。

  细节有点多。


代码

  1. #include <cstring>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cmath>
  5. #include <cstdlib>
  6. using namespace std;
  7. const int N=1000005,mod=1e9;
  8. int n,m,ad,k,v[N*4],fa[N*4];
  9. struct color{
  10. int a,b,c;
  11. }co[N];
  12. int Turn(int a,int b){
  13. return a==1?(b-1):(a-1+m-1);
  14. }
  15. int getf(int k){
  16. return fa[k]==k?k:fa[k]=getf(fa[k]);
  17. }
  18. int solve(){
  19. memset(v,-1,sizeof v);
  20. for (int i=1;i<=ad*2;i++)
  21. fa[i]=i;
  22. for (int i=1;i<=k;i++){
  23. int a=co[i].a,b=co[i].b,c=co[i].c;
  24. if (a==1&&b==1)
  25. continue;
  26. if (a==1||b==1){
  27. v[Turn(a,b)]=c,v[Turn(a,b)+ad]=c^1;
  28. continue;
  29. }
  30. int A=Turn(a,1),B=Turn(1,b);
  31. int res=(!(a&1)&&!(b&1))^c;
  32. if (res){
  33. if (getf(A)==getf(B))
  34. return 0;
  35. fa[getf(A)]=getf(B+ad);
  36. fa[getf(B)]=getf(A+ad);
  37. }
  38. else {
  39. if (getf(A)==getf(B+ad))
  40. return 0;
  41. fa[getf(A)]=getf(B);
  42. fa[getf(A+ad)]=getf(B+ad);
  43. }
  44. }
  45. for (int i=1;i<=ad*2;i++){
  46. if (v[i]==-1)
  47. continue;
  48. if (v[getf(i)]==-1)
  49. v[getf(i)]=v[i];
  50. else if (v[getf(i)]!=v[i])
  51. return 0;
  52. }
  53. int res=1,ans=0;
  54. for (int i=1;i<=ad*2;i++)
  55. if (getf(i)==i&&v[i]==-1)
  56. ans++;
  57. for (ans>>=1;ans--;)
  58. res=res*2%mod;
  59. return res;
  60. }
  61. int main(){
  62. scanf("%d%d%d",&n,&m,&k);
  63. ad=n+m-2;
  64. int flag=-1;
  65. for (int i=1;i<=k;i++){
  66. scanf("%d%d%d",&co[i].a,&co[i].b,&co[i].c);
  67. if (co[i].a==1&&co[i].b==1)
  68. flag=co[i].c;
  69. }
  70. int ans1=solve();
  71. for (int i=1;i<=k;i++)
  72. if (co[i].a>1&&co[i].b>1)
  73. co[i].c^=1;
  74. int ans2=solve();
  75. int ans=0;
  76. if (flag==-1)
  77. ans=(ans1+ans2)%mod;
  78. else
  79. ans=flag?ans2:ans1;
  80. printf("%d",ans);
  81. return 0;
  82. }

  

BZOJ2303 [Apio2011]方格染色 并查集的更多相关文章

  1. BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]

    题意: $n*m:n,m \le 10^6$的网格,每个$2 \times 2$的方格必须有1个或3个涂成红色,其余涂成蓝色 有一些方格已经有颜色 求方案数 太神了!!!花我三节课 首先想了一下只有两 ...

  2. [BZOJ2303][Apio2011]方格染色

    [BZOJ2303][Apio2011]方格染色 试题描述 Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好,他们想要表格中每个2 × ...

  3. BZOJ2303: [Apio2011]方格染色 【并查集】

    Description Sam和他的妹妹Sara有一个包含n × m个方格的表格.她们想要将其的每个方格都染成红色或蓝色.出于个人喜好,他们想要表格中每个2 × 2的方形区域都包含奇数个(1 个或 3 ...

  4. BZOJ2303 APIO2011方格染色

    这题太神了 首先我们可以发现只有当i和j都是偶数时a[1][1]^a[1][j]^a[i][1]^a[i][j]=1才满足情况,其它时都为0 所以我们可以先把i和j都为偶数的地方^1变为0 下面才是最 ...

  5. BZOJ2303 APIO2011方格染色(并查集)

    比较难想到的是将题目中的要求看做异或.那么有ai,j^ai+1,j^ai,j+1^ai+1,j+1=1.瞎化一化可以大胆猜想得到a1,1^a1,j^ai,1^ai,j=(i-1)*(j-1)& ...

  6. BZOJ_2303_[Apio2011]方格染色 _并查集

    BZOJ_2303_[Apio2011]方格染色 _并查集 Description Sam和他的妹妹Sara有一个包含n × m个方格的 表格.她们想要将其的每个方格都染成红色或蓝色. 出于个人喜好, ...

  7. bzoj 2303: [Apio2011]方格染色【并查集】

    画图可知,每一行的状态转移到下一行只有两种:奇数列不变,偶数列^1:偶数列不变,奇数列^1 所以同一行相邻的变革染色格子要放到同一个并查集里,表示这个联通块里的列是联动的 最后统计下联通块数(不包括第 ...

  8. bzoj 2303: [Apio2011]方格染色

    传送门 Description Sam和他的妹妹Sara有一个包含n × m个方格的表格.她们想要将其的每个方格都染成红色或蓝色.出于个人喜好,他们想要表格中每个2 × 2的方形区域都包含奇数个(1 ...

  9. 【题解】P3631 [APIO2011]方格染色

    很有意思的一道题,所以单独拿出来了. 完整分享看 这里 题目链接 luogu 题意 有一个包含 \(n \times m\) 个方格的表格.要将其中的每个方格都染成红色或蓝色.表格中每个 \(2 \t ...

随机推荐

  1. Jacob 调用金税系统

    1.调用打印方法时,若是有预览弹窗提示,程序会阻塞住,并在控制台打印一行: C:\Program Files (x86)\��Ʊ���\914601007603699430.0\Config\Prin ...

  2. C++中模板的使用

    为什么使用模板: C++重载(overloading),重载函数一般含有不同的参数个数或不同的参数类型.如果使用MAX函数对不同类型的求最大值,就要定义不同的重载函数: int max(int x,i ...

  3. .NET 单点登录开源项目

    1. https://www.apereo.org/cas/client-integration 2.源码下载 https://wiki.jasig.org/display/CASC/.Net+Cas ...

  4. 完整版ffmpeg使用情况

    protected void Page_Load(object sender, EventArgs e) { string filePath = @"D:/Prjects/MT147/exa ...

  5. ABAP知识点笔记

    1,获取光标所在行 READ TABLE TD_ALV_DATA INTO TH_ALV_DATA INDEX RS_SELFIELD-TABINDEX. 2,获取alv可编辑单元格内容 DATA: ...

  6. Django-Model操作数据库(增删改查、连表结构)

    一.数据库操作 1.创建model表         基本结构 1 2 3 4 5 6 from django.db import models     class userinfo(models.M ...

  7. KERMIT,XMODEM,YMODEM,ZMODEM传输协议小结

    转:http://blog.163.com/czblaze_3333/blog/static/208996228201272295236713/ Kermit协议 报文格式: 1.       MAR ...

  8. pytorch官网上两个例程

    caffe用起来太笨重了,最近转到pytorch,用起来实在不要太方便,上手也非常快,这里贴一下pytorch官网上的两个小例程,掌握一下它的用法: 例程一:利用nn  这个module构建网络,实现 ...

  9. git操作之冲突解决

    应用场景,任哥,我两个人共同修改了git项目上的一个文件.zsh命令行模式 准备工作 简写命令解释 gl=git pullgp=git pushgst=git statusgcmsg=git comm ...

  10. git强制覆盖更新

    1.选择项目,右键选择Team,选择Team里面的Reset. 2.点击Reset后弹出Reset窗口,选择Hard选项,这样就会把远端的项目完全拉下来覆盖本地,本地没有的文件也会被创建,点击确定.