zoukankan      html  css  js  c++  java
  • CF1344F Piet's Palette【线性代数】

    设一个 ( exttt{RYB}) 字符串混合的结果为做如下操作直到字符串长度 (le 1):若开头两个字符不同,将其替换为一个与这两个字符都不同的字符;否则将这两项删去。

    若最终序列长度 (=1) 则结果即为唯一的字符,否则为 ( exttt W)

    有一个长为 (n) 的字符串,其中有些位置是空的,(k) 次操作:

    • ( exttt{mix m j_1 j_2 }cdots exttt{ j_m c}):将第 (j_1,cdots,j_m) 个字符按顺序混合,得到字符 (c)
    • ( exttt{RY/RB/YB m j_1 j_2 }cdots exttt{ j_m}):将第 (j_1,cdots,j_m) 个字符交换 ( exttt{RY/RB/YB})

    构造出合法的原字符串。需判断无解。

    (n,kle 10^3)


    很容易发现 ( exttt{W/.RYB}) 代表 (0,1,2,3),混合即为异或和。然后发现不太好处理交换操作。

    不容易发现交换操作是线性变换,因此我们可以把每个数拆成两个基底 (a_i,b_i) 的线性组合,初始时 (a_i=1,b_i=2),则 ( exttt{RY/RB/YB}) 分别是 swap(a[i],b[i])b[i] ^= a[i]a[i] ^= b[i]

    然后解一个 (2n)(2k) 个方程的方程组即可,时间复杂度是三方的。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2003;
    template<typename T>
    void read(T &x){
        int ch = getchar(); x = 0;
        for(;ch < '0' || ch > '9';ch = getchar());
        for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    }
    int n, m, k, a[N], b[N], ans[N];
    bitset<N> bas[N];
    void ins(bitset<N> val){
        for(int i = 0;i < (n<<1);++ i) if(val[i]){
            if(bas[i].none()){bas[i] = val; return;}
            val ^= bas[i];
        } if(val[n<<1]){puts("NO"); exit(0);}
    }
    int ID(char x){
        switch(x){
        case 'R': return 1;
        case 'Y': return 2;
        case 'B': return 3;
        default: return 0;
        }
    }
    int main(){
        read(n); read(k);
        for(int i = 0;i < n;++ i){a[i] = 1; b[i] = 2;}
        while(k --){
            char opt[4], col[2]; scanf("%s%d", opt, &m);
            if(opt[0] == 'm'){
                bitset<N> e1, e2;
                while(m --){
                    int x; read(x); -- x;
                    e1[x<<1] = a[x]&1; e1[x<<1|1] = a[x]>>1;
                    e2[x<<1] = b[x]&1; e2[x<<1|1] = b[x]>>1;
                } scanf("%s", col);
                int id = ID(col[0]);
                e1[n<<1] = id&1; e2[n<<1] = id>>1;
                ins(e1); ins(e2);
            } else if(opt[0] == 'R' && opt[1] == 'Y'){
                while(m --){int x; read(x); -- x; swap(a[x], b[x]);}
            } else if(opt[0] == 'R' && opt[1] == 'B'){
                while(m --){int x; read(x); -- x; b[x] ^= a[x];}
            } else {
                while(m --){int x; read(x); -- x; a[x] ^= b[x];}
            }
        }
        for(int i = (n<<1)-1;~i;-- i){
            ans[i] = bas[i][n<<1];
            for(int j = i-1;~j;-- j)
                if(bas[j][i]) bas[j] ^= bas[i];
        } puts("YES");
        for(int i = 0;i < n;++ i) putchar(".RYB"[ans[i<<1]|ans[i<<1|1]<<1]);
    }
    
  • 相关阅读:
    使用freemarker生成word,步骤详解并奉上源代码
    汉诺塔问题
    java interview
    java 反射
    java 匿名内部类
    java 内部类(转)
    MYSQL和ORACLE的一些区别
    Hibernate总结(转)
    Hibernate的使用
    Arduino LM35温度检测
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14701909.html
Copyright © 2011-2022 走看看