【BZOJ1434】【codevs2348】染色游戏,博弈

来源:互联网 发布:老鼠 知乎 编辑:程序博客网 时间:2024/06/05 16:25

传送门1
传送门2
思路:
一开始我煞笔了,以为联通块是一个矩形,然后就像预处理+矩阵前缀和优化blabla,发现怎么都不对,最后突然意识到这个联通块不是一个规则的东西,然后就zz了
打表发现当i!=1且j!=1时sg的值就是2i+j1,但是i=1或j=1时就有点蛋疼了
因为暴力写的是指数级的所以打的表很小,只是4*5的表,然后又打个1*10的表,有点发现规律但还不是很好描述
无奈看题解(啪)
woc竟然是lowbit(i+j-1)?
好吧,是我煞笔了
但是n,m<=100,数字太大怎么表示?
因为这些sg中用二进制表示的话都是只有一个1的(最高位)
所以我们可以只存这个最高位的1就可以了
最后扫一遍看是否有1就行了
这题调了一晚上,因为暴力写挂了(?)
9.24
昨晚突然又想到一些东西,实际上打1*n的表时间复杂度是O(n2)的,也就是说很容易打出来1*100的表,到时候就算看不出来是lowbit,也可以看出来每个数都只有一个二进制位的1,说白了就是过度依赖题解了,觉得自己做不出来,而没有去认真思考
代码:

#include<cstdio>#include<cstring>#include<cmath>using namespace std;int n,m,T;bool vis[202];int in(){    char ch=getchar();    while (ch!='H'&&ch!='T') ch=getchar();    return ch=='H';}void work(){    memset(vis,0,sizeof(vis));    scanf("%d%d",&n,&m);    int t;    for (int i=1;i<=n;++i)        for (int j=1;j<=m;++j)            if (!in())                if (i==1||j==1) vis[(int)log2((i+j-1)&(-i-j+1))+1]^=1;                else vis[i+j-1]^=1;    for (int i=1;i<=n+m;++i)        if (vis[i])            return void(puts("-_-"));    puts("=_=");}main(){for (scanf("%d",&T);T;--T) work();}
0 0
原创粉丝点击