zoukankan      html  css  js  c++  java
  • TC8744

    (今天 vj 挂掉了,但是意外找到国内镜像站,以后再也不用担心 vj 挂掉啦!)

    把每个格子选或不选当变量,对每个格子列异或方程组,得到一个 (nm imes nm) 的异或方程。高消硬解复杂度是 (mathrm O!left((nm)^3 ight)),就算秩只有 (1)(显然不可能),再 bitset 优化,复杂度 (mathrm O!left(dfrac{(nm)^2}w ight))​ 那还是够呛。

    那只能考虑逻辑优化,方法是减少变量和方程的数量。看哪些变量可以被其他变量表示,手动(而不是让高斯消元来)代入消元,既可减少变量也可减少方程。注意到一个点处列的方程涉及到的格子只会在 (pm2) 行出现。那就考虑试图将 (+2) 行的变量用前 (4) 行的变量表示。从最上面开始的话其实只有 (2) 行,因为再往上就没有了。

    ((1,1)) 的方程,只有一个点是在 (+2) 行的。从 ((1,2)) 开始,会有两个点在 (+2) 行,这就不好了。考虑令 ((3,1)) 与上面两行有同等地位,这样就可以一路递推,将 ((3,2sim m)) 都用基本地位的格子表示出来。然后便可以接着往下递推了。这样一来,新变量只有前两行和第一列的并,是 (mathrm O(n)) 级别的(假设 (n=mathrm O(m))),而其它旧变量都可以表示成新变量的线性组合(可能再平移上 (1),无妨)。这样表示只是满足条件的一个必要条件,因为最后两行和最后一列对应的方程还没得到检验。那就把这些方程列出来然后解哇,这样方程数和变量数都是 (mathrm O(n)) 了,妥妥的。最后答案就是 (2) 的自由变量次方。

    递推求线性表出式的时候,注意到这并不是严格意义上的线性组合,可能平移 (1),那就给常数项也分配一个位置,照样操作。(n=1) 的时候会出问题,但注意到 (n,m) 是对称的,如果不是 (n=m=1) 那就可以 swap,否则直接输出 1

    code
    #include<bits/stdc++.h>
    using namespace std;
    #define mp make_pair
    #define X first
    #define Y second
    #define pb push_back
    const int mod=123456789,inf=0x3f3f3f3f;
    const int N=160;
    int n,m;
    vector<bitset<3*N> > a;
    bitset<3*N> xsm[N][N];
    const int dx[]={-1,-1,-2,-2,1,1,2,2},dy[]={2,-2,1,-1,2,-2,1,-1};
    bool ok(int x,int y){return 1<=x&&x<=n&&1<=y&&y<=m;}
    void gauss(){
    	for(int i=0;;i++){
    		pair<int,int> p(inf,inf);
    		for(int j=i;j<a.size();j++)if(a[j].any()){
    			int x=a[j]._Find_first();
    			p=min(p,mp(x,j));
    		}
    		int col=p.X,row=p.Y;
    		if(row==inf)break;
    		swap(a[i],a[row]);
    		for(int j=0;j<a.size();j++)if(j!=i&&a[j][col])a[j]=a[j]^a[i];
    	}
    }
    struct KnightsOut{
    	int count(int _n,int _m){
    		n=_n,m=_m;
    		if(n==1&&m==1)return 1;
    		if(n==1)swap(n,m);
    		int now=0;
    		for(int i=1;i<=2;i++)for(int j=1;j<=m;j++)xsm[i][j].set(++now);
    		for(int i=3;i<=n;i++)xsm[i][1].set(++now);
    		for(int i=1;i<=n-2;i++)for(int j=1;j<=m-1;j++){
    			bitset<3*N> &nw=xsm[i+2][j+1];
    			nw.set(now+1),nw^=xsm[i][j];
    			for(int k=0;k<8;k++){
    				int x=i+dx[k],y=j+dy[k];
    				if(ok(x,y)&&!(x==i+2&&y==j+1))nw^=xsm[x][y];
    			}
    		}
    		for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(i>n-2||j>m-1){
    			bitset<3*N> nw;
    			nw.set(now+1),nw^=xsm[i][j];
    			for(int k=0;k<8;k++){
    				int x=i+dx[k],y=j+dy[k];
    				if(ok(x,y))nw^=xsm[x][y];
    			}
    			a.pb(nw);
    		}
    		gauss();
    		int cnt=now,ans=1;
    		for(int i=0;i<a.size();i++)if(a[i].any()){
    			int x=a[i]._Find_first();
    			if(x==now+1)return 0;
    			cnt--;
    		}
    		while(cnt--)ans=2*ans%mod;
    		return ans;
    	}
    };
    
    珍爱生命,远离抄袭!
  • 相关阅读:
    validform使用
    kindeditor使用
    初探uni-app
    【心有猛虎】react-lesson
    【心有猛虎】react-pxq
    【水滴石穿】douban-movies-react-native
    【水滴石穿】MyFirstRNDemo
    【水滴石穿】github_popular
    笔记本CPU的型号和类型的区分方法
    List<T>的IndexOf方法和Remove方法
  • 原文地址:https://www.cnblogs.com/ycx-akioi/p/solution-tc8744.html
Copyright © 2011-2022 走看看