[COGS1464] [NOI1996]三角形灯塔

来源:互联网 发布:网络推广总监 编辑:程序博客网 时间:2024/04/28 19:09
  • ALG : 高斯消元解异或方程组+无解判定+自由元个数判定

首先设最下面一排的灯为元x1,x2,x3,,xn
那么任何一个灯都会得到一个由一些元异或得到结果的式子

eg:
01234
1@
2@@
3@@@
4@@@@

设最下面的四个灯为x1,x2,x3,x4,

(3,1)代表的式子为 x1x2=w
(2,1)代表的式子为 x1x2x2x3=x1x3=w

所以说对于给出的每一个灯都会得到一个式子,对这些式子解异或方程组即可.


无解情况:
出现式子形如

(0x1)(0x2)(0x3)(0x4)x1(0xn)=w

w>0

时无解


自由元个数:
这个就是高斯消元的姿势问题了…
设当前消元到了第k+1
1. 找到一个1,使其不再前k行中,且不再前k列中
2. 经过列交换与行交换将其移到(k+1,k+1)位置
3. 当不能找到这样的1时,则前k个元不是自由元


设自由元个数为free
答案即为2free.


/****************************************\* Author : ztx* Title  : [cogs] 1464. [NOI1996]三角形灯塔* ALG    : 高斯消元解异或方程组+无解判定+自由元个数判定QAQ* CMT    : * Time   : \****************************************/#include <cstdio>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define rep(i,l,r) for(i=(l);i< (r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)#define rev(i,r,l) for(i=(r);i> (l);i--)typedef long long ll ;int CH , NEG ;template <typename TP>inline void read(TP& ret) {    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;    if (CH == '-') NEG = true , CH = getchar() ;    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;    if (NEG) ret = -ret ;}template <typename TP>inline void readc(TP& ret) {    while (ret=getchar() , ret<'!') ;    while (CH=getchar() , CH>'!') ;}template <typename TP>inline void reads(TP *ret) {    ret[0]=0;while (CH=getchar() , CH<'!') ;    while (ret[++ret[0]]=CH,CH=getchar(),CH>'!') ;}#include <algorithm>namespace Gauss {    #define  maxn  55    #define  maxm  55    #define  eps   1E-10    int a[maxn][maxm] = {0} , col , row , know ;    inline void work() {        int i , j , k ; know = 0 ;/*      rep (i,1,col) Rep (j,i,row) if (a[j][i]) {            know ++ ;            if (i!=j) std::swap(a[i],a[j]) ;            Rep (j,1,row) if (i!=j && a[j][i])                Rev (k,col,i) a[j][k] ^= a[i][k] ;            break ;        }*/        rep (know,0,row) {            rep (i,know+1,col) Rep (j,know+1,row)                if (a[j][i]) goto Found ;            continue ;            Found:;            /* swap col know+1 & col i */            if (know+1 != i)                Rep (k,1,row) std::swap(a[k][know+1],a[k][i]) ;            /* swap row j & row know+1 */            if (know+1 != j)                Rep (k,1,col) std::swap(a[know+1][k],a[j][k]) ;            i = know+1 ;            Rep (j,1,row) if (i!=j && a[j][i])                Rev (k,col,i) a[j][k] ^= a[i][k] ;        }    }    inline bool NoSolution() {        int i , j ;        Rep (i,1,row) {            rep (j,1,col) if (a[i][j]) break ;            if (j==col && a[i][col]) return true ; // (0,0,0,...,0,1)        }        return false ;    }    #undef  maxn    #undef  maxm    #undef  eps}using namespace Gauss ;inline void Getmodulus(int r,int L,int R) {int i , j ;    a[r][R] = 1 ;    if (L == R) return ;    a[r][R-1] = 1 ;    while (!a[r][L]) rep (j,L,R) a[r][j] = a[r][j]^a[r][j+1] ;}int main() {int l , r , i , j , w , n ;ll ans ;    #define READ    #ifdef  READ        freopen("lighthouse.in" ,"r",stdin ) ;        freopen("lighthouse.out","w",stdout) ;    #endif    scanf("%d", &n) ;    col = n+1 ;    row = 0 ;    while (scanf("%d%d%d", &r , &l , &w) != EOF) {        if (!l && !r && !w) break ;/* SMG */        a[++row][col] = w ;        r = l+n-r ;        Getmodulus(row,l,r) ;/*        Rep (i,l,r) a[row][i] = 1 ;        这个姿势是完全不对的QAQ*/    }    work() ;    if (NoSolution()) {        puts("No Answer!") ;        goto END;    }    ans = 1<<(n-know) ;    printf("%lld\n", ans) ;    END:;    #ifdef  READ        fclose(stdin) ; fclose(stdout) ;    #else        getchar() ; getchar() ;    #endif    return 0 ;}
0 0
原创粉丝点击