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

解题:CQOI 2013 和谐矩阵

时间:2018-10-02 20:22:12      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:检查   play   技术分享   hide   amp   org   name   \n   cstring   

题面

踩踩时间复杂度不正确的高斯消元

首先可以发现第一行确定后就可以确定整个矩阵,所以可以枚举第一行的所有状态然后$O(n)$递推检查是否合法

$O(n)$递推的方法是这样的:设$pre$为上一行,$now$为当前行,$nxt$为递推出的下一行,$all$为列的全集,则可以直接用位运算完成递推:

$nxt=all\&((now<<1)xor(now>>1)xor$ $now$ $xor$ $pre)$

递推后第$n+1$行为空则说明可行

问题来了,第一行的状态有$O(2^{40})$种,会$T$。但是有一个鬼畜的性质是如果存在合法解一定有一个对称的合法解,然后就可以$O(n*2^{\frac{n}{2}})$出解了=。=

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=50;
 6 int mapp[N][N];
 7 long long n,m,mid,all,half;
 8 long long fir,las,noww,tmp;
 9 int check(int a,int b)
10 {
11     return mapp[a][b]^mapp[a-1][b]^mapp[a][b-1]^mapp[a][b+1];
12 }
13 int main ()
14 {
15     scanf("%lld%lld",&n,&m);
16     mid=(m+1)/2,all=(1ll<<m)-1,half=(1ll<<mid)-1;
17     for(int i=1;i<=half;i++)
18     {
19         fir=0;
20         for(int j=1;j<=mid;j++)
21             if(i&(1ll<<(j-1))) fir|=(1ll<<(j-1))|(1ll<<(m-j));
22         las=noww=all&(fir^(fir<<1)^(fir>>1)),tmp=fir;
23         for(int j=2;j<=n;j++)
24             las=noww,noww=all&(noww^(noww<<1)^(noww>>1)^tmp),tmp=las;
25         if(!noww) break;
26     }
27     for(int i=1;i<=m;i++)
28         mapp[1][i]=(fir&(1ll<<(i-1)))?1:0;
29     for(int i=2;i<=n;i++)
30         for(int j=1;j<=m;j++)
31             mapp[i][j]=check(i-1,j);
32     for(int i=1;i<=n;i++)
33     {
34         for(int j=1;j<=m;j++)
35             printf("%d ",mapp[i][j]);
36         printf("\n");
37     }
38     return 0;
39 }
View Code

 

解题:CQOI 2013 和谐矩阵

标签:检查   play   技术分享   hide   amp   org   name   \n   cstring   

原文地址:https://www.cnblogs.com/ydnhaha/p/9737308.html

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