• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            【異或(XOR)運(yùn)算由于與“奇偶性”密切相關(guān),經(jīng)常出現(xiàn)在有關(guān)奇偶性和二進(jìn)制的題目中】
            很多異或問題都要涉及到解異或方程組,因此首先要搞懂異或方程組的解法。

            (1)異或方程組的格式(設(shè)有n個(gè)未知數(shù),m個(gè)方程):
            a11*x1 XOR a12*x2 XOR ... XOR a1n*xn = b1
            a21*x1 XOR a22*x2 XOR ... XOR a2n*xn = b2
            ……………………………………………………
            am1*x1 XOR am2*x2 XOR ... XOR amn*xn = bm
            其中的所有a、b、x的值均為0或1。解異或方程組就是給出了所有的系數(shù)a和b之后,求出解(x1, x2 ... xn)。一般來說,題目的要求無非就是如下幾種:<1>求任意一組解;<2>求解的總數(shù);<3>求出最優(yōu)解(比如字典序最小的解或者加權(quán)以后權(quán)值最大/小的解等)。

            (2)求解異或方程組的離線算法:
            整體思想與普通方程組的高斯消元解法類似。
            第一階段(消元):設(shè)置一個(gè)變量p,一開始p=1,然后,i從1到n,每次執(zhí)行:<1>若在第p個(gè)及以后的方程中,至少有一個(gè)方程的xi系數(shù)為1,設(shè)為第q個(gè)方程,則先將第p、q個(gè)方程交換,然后用第p個(gè)方程去XOR后面剩下的所有xi系數(shù)為1的方程(各系數(shù)包括b都對(duì)應(yīng)進(jìn)行XOR運(yùn)算,實(shí)際上就是矩陣初等行變換),將它們的xi系數(shù)均變成0,最后p加1;<2>否則(第p個(gè)及以后的方程中xi系數(shù)均為0),xi是自由元(xi不管是取0還是1,都能導(dǎo)出整個(gè)方程組的一個(gè)解),按照自由元處理(隨便定值,然后將前面所有xi系數(shù)為1的方程全部代入xi的值XOR掉),p值不變。(感謝HN SYJ神犇,在總結(jié)中講到了如果遇到自由元的話p值是不能變的,否則會(huì)疵,見這里
            第二階段(回代求解):在第一階段結(jié)束后,若出現(xiàn)了S個(gè)自由元,則會(huì)在整個(gè)方程組的最后出現(xiàn)S個(gè)多余方程,它們的等號(hào)左邊所有系數(shù)均為0(顯然值也為0)。對(duì)于這些多余方程,如果有等號(hào)右邊為1的,則整個(gè)方程組無解。否則,如果所有多余方程的等號(hào)右邊均為0,則整個(gè)方程組有2S個(gè)解(因?yàn)镾個(gè)自由元可以隨便取值,都能導(dǎo)出解)。如果要求具體的解,則從第(m-S)個(gè)方程開始,往回代,設(shè)立變量p,初始p=m-S,逆序枚舉每個(gè)未知數(shù)(自由元除外),對(duì)于未知數(shù)xi,可以從第p個(gè)方程中直接得到其值(因?yàn)榇藭r(shí)第p個(gè)方程等號(hào)左邊必然只有xi系數(shù)為1,等號(hào)右邊是幾,xi值就是幾),然后,將之前的所有xi系數(shù)為1的方程全部用第p個(gè)方程XOR掉,p--。
            具體實(shí)現(xiàn)的時(shí)候有一些技巧:
            1)在第一階段第<1>步XOR的時(shí)候,實(shí)際上只要枚舉xi及其后面的未知數(shù)就行了,因?yàn)榍懊娴奈粗獢?shù)已經(jīng)消掉了;在第<2>步XOR的時(shí)候,只需要xi和等號(hào)右邊的系數(shù)b,因?yàn)槠渌南禂?shù)均為0;
            2)第一階段的p可以直接留到第二階段繼續(xù)用,只不過要減1。

            (3)求解異或方程組的在線算法:
            這里的在線算法其實(shí)指的是,它可以隨時(shí)在后面增加新的方程,直接擴(kuò)展已求出的解以及更新解的總數(shù),而不用每次重新求解。這個(gè)算法在某些求”XOR值最大“的問題中顯然比較有用。
            為了講清楚這個(gè)算法,首先要引入”關(guān)鍵元“:在消元過程中,每個(gè)方程有至多一個(gè)”關(guān)鍵元“,它決定了該方程可以去XOR后面的哪種方程。設(shè)C[i]為關(guān)鍵元為xi的方程編號(hào),若C[i]==-1(以xi為關(guān)鍵元的方程不存在),則xi為自由元,反之亦然。一開始,所有的C值均為-1。
            在新加入一個(gè)方程時(shí),i從1到n枚舉,若該方程xi系數(shù)為1,則看一下C[i]是否為-1,若為-1,則xi為該方程關(guān)鍵元,C[i]設(shè)為該方程編號(hào),結(jié)束(此時(shí),xi不再是自由元,因此整個(gè)方程組解的總數(shù)減半);若不為-1,則用編號(hào)C[i]的方程去XOR該方程(其實(shí)只要XOR xi及其之后的部分),將該方程中的xi消去。如果最終i枚舉到n時(shí)仍然木有找到關(guān)鍵元,則該方程無關(guān)鍵元,也就是說該方程是一個(gè)多余方程(0=0或0=1),如果是0=0,則不影響解的總數(shù),如果是0=1,則整個(gè)方程組無解了。
            如果要求具體的解,則與離線算法的第二階段類似,只是回代求解時(shí),p不能再是逆序的了,而應(yīng)該是每個(gè)C[i]的值。此外,對(duì)于C[i]==-1的(即xi是自由元),隨便定值,并代到所有方程中XOR掉它。

            顯然,以上兩種算法的時(shí)間復(fù)雜度均為O(n2m)。

            (4)算法常數(shù)優(yōu)化——壓位:
            在具體實(shí)現(xiàn)的時(shí)候,需要用一個(gè)bool矩陣A[m][n+1]來存儲(chǔ)所有的系數(shù)(a、b),這樣很浪費(fèi),因?yàn)橥耆梢杂靡粋€(gè)int矩陣,一下存儲(chǔ)32位。這種壓位思想可以帶來常數(shù)上的優(yōu)化,因?yàn)樵谟靡粋€(gè)方程去XOR另一個(gè)時(shí),時(shí)間將變?yōu)樵瓉淼?/32。
            實(shí)現(xiàn)起來比不壓位的要麻煩一些。具體來說,首先,調(diào)用原矩陣的第i行第j列是否為1需要寫成A[i][j/32] & (1 << (j % 32))(原矩陣第i行第j列為0當(dāng)且僅當(dāng)該值為0),對(duì)于等號(hào)右邊的b系數(shù),在原矩陣中為第n列,因此寫成A[i][n/32] & (1 << (n % 32))。在實(shí)現(xiàn)過程中,為了避免重復(fù)計(jì)算,可以設(shè)n0=n/32,q=n%32,q0=j/32,q1=j%32,n0和q預(yù)先算出,在枚舉j(未知數(shù)編號(hào))時(shí)維護(hù)q0、q1。
            另外需要嚴(yán)重注意的是:在求出了某個(gè)未知數(shù)xi的值之后代入到其它方程中時(shí),如果是單個(gè)代入不整體XOR,則i和n列都要處理,但如果是整體XOR,則要特判一下i和n列在壓位之后是否壓到同一位里了,若壓到同一位里則只能XOR一次!?。。。。。。?!
            (其實(shí)是可以壓64位的,但由于long long的常數(shù)較大且在求1<<q時(shí)還要強(qiáng)制類型轉(zhuǎn)換,所以得不償失,不如壓32位快)

            例題:JSOI2012 arc
            建模方法:設(shè)一組解(x1, x2 ... xn)為:xi==0當(dāng)且僅當(dāng)i在上游。對(duì)于原圖中給出的有向圖,若i的出度為偶數(shù),則需要滿足i指向的那些點(diǎn)的x值XOR之和為0即可(不管xi是0還是1);若i的出度為奇數(shù),則需要滿足i及其指向的那些點(diǎn)的x值的XOR之和為1即可(不管xi是0還是1)。這樣就轉(zhuǎn)化為求異或方程組的特解問題,假設(shè)在求解過程中,對(duì)于所有的自由元均定為0。
            代碼(均為壓位之后的):
            離線算法:
            #include <iostream>
            #include 
            <stdio.h>
            #include 
            <stdlib.h>
            #include 
            <string.h>
            #include 
            <time.h>
            using namespace std;
            #define re(i, n) for (int i=0; i<n; i++)
            #define re1(i, n) for (int i=1; i<=n; i++)
            #define re2(i, l, r) for (int i=l; i<r; i++)
            #define re3(i, l, r) for (int i=l; i<=r; i++)
            #define rre(i, n) for (int i=n-1; i>=0; i--)
            #define rre1(i, n) for (int i=n; i>0; i--)
            #define rre2(i, r, l) for (int i=r-1; i>=l; i--)
            #define rre3(i, r, l) for (int i=r; i>=l; i--)
            #define ll long long
            const int MAXN = 2005, KS = 32, MAXN0 = (MAXN + 1/ KS + 1, INF = ~0U >> 2;
            int n, n0, q, A[MAXN][MAXN0];
            bool res[MAXN], res_ex = 1;
            void init()
            {
                freopen(
            "arc.in""r", stdin);
                
            int q0 = 0, q1 = 0, x, y;
                scanf(
            "%d"&n); n0 = n / KS; q = n % KS;
                re(i, n) {
                    scanf(
            "%d"&x);
                    
            if (x & 1) {A[i][q0] |= 1 << q1; A[i][n0] |= 1 << q;}
                    re(j, x) {scanf(
            "%d"&y); y--; A[i][y / KS] |= 1 << (y % KS);}
                    
            if (q1 == KS - 1) {q0++; q1 = 0;} else q1++;
                }
                fclose(stdin);
            }
            void solve()
            {
                
            int q0 = 0, q1 = 0, p = 0, x;
                ll tmp;
                re(i, n) {
                    x 
            = -1;
                    re2(j, p, n) 
            if (A[j][q0] & (1 << q1)) {x = j; break;}
                    
            if (x >= 0) {
                        
            if (x != p) {re3(k, q0, n0) {tmp = A[x][k]; A[x][k] = A[p][k]; A[p][k] = tmp;}}
                        re2(j, p
            +1, n) if (A[j][q0] & (1 << q1)) re3(k, q0, n0) A[j][k] ^= A[p][k];
                        p
            ++;
                    } 
            else {
                        res[i] 
            = 1;
                        re(j, p) 
            if (A[j][q0] & (1 << q1)) {A[j][q0] &= ~(1 << q1); A[j][n0] ^= 1 << q;}
                    }
                    
            if (q1 == KS - 1) {q0++; q1 = 0;} else q1++;
                }
                re2(i, p, n) 
            if (A[i][n0] & (1 << q)) {res_ex = 0return;} p--;
                rre(i, n) {
                    
            if (q1) q1--else {q0--; q1 = KS - 1;}
                    
            if (!res[i]) {
                        res[i] 
            = A[p][n0] & (1 << q);
                        re(j, p) 
            if (A[j][q0] & (1 << q1)) {
                            A[j][q0] 
            ^= A[p][q0]; if (q0 < n0) A[j][n0] ^= A[p][n0];
                        }
                        p
            --;
                    }
                }
            }
            void pri()
            {
                freopen(
            "arc.out""w", stdout);
                
            if (res_ex) {
                    
            int sum = 0bool SPC = 0;
                    re(i, n) 
            if (!res[i]) sum++;
                    printf(
            "%d\n", sum);
                    re(i, n) 
            if (!res[i]) {
                        
            if (SPC) putchar(' '); else SPC = 1;
                        printf(
            "%d", i + 1);
                    }
                    puts(
            "");
                } 
            else puts("Impossible");
                fclose(stdout);
            }
            int main()
            {
                init();
                solve();
                pri();
                
            return 0;
            }
            在線算法:
            #include <iostream>
            #include 
            <stdio.h>
            #include 
            <stdlib.h>
            #include 
            <string.h>
            using namespace std;
            #define re(i, n) for (int i=0; i<n; i++)
            #define re1(i, n) for (int i=1; i<=n; i++)
            #define re2(i, l, r) for (int i=l; i<r; i++)
            #define re3(i, l, r) for (int i=l; i<=r; i++)
            #define rre(i, n) for (int i=n-1; i>=0; i--)
            #define rre1(i, n) for (int i=n; i>0; i--)
            #define rre2(i, r, l) for (int i=r-1; i>=l; i--)
            #define rre3(i, r, l) for (int i=r; i>=l; i--)
            #define ll long long
            const int MAXN = 2005, KS = 32, MAXN0 = (MAXN + 1/ KS + 1, INF = ~0U >> 2;
            int n, n0, q, A[MAXN][MAXN0], B[MAXN];
            bool C[MAXN], res[MAXN], res_ex = 1;
            void init()
            {
                freopen(
            "arc.in""r", stdin);
                
            int q0 = 0, q1 = 0, x, y, _q0, _q1;
                scanf(
            "%d"&n); n0 = n / KS; q = n % KS;
                re(i, n) {
                    scanf(
            "%d"&x);
                    
            if (x & 1) {A[i][q0] |= 1 << q1; A[i][n0] |= 1 << q;}
                    re(j, x) {
                        scanf(
            "%d"&y); y--; _q0 = y / KS; _q1 = y % KS;
                        A[i][_q0] 
            |= 1 << _q1;
                    }
                    
            if (q1 == KS - 1) {q0++; q1 = 0;} else q1++;
                }
                fclose(stdin);
            }
            void solve()
            {
                re(i, n) B[i] 
            = -1;
                
            int q0, q1, x;
                re(i, n) {
                    q0 
            = q1 = 0;
                    re(j, n) {
                        
            if (A[i][q0] & (1 << q1)) {
                            x 
            = B[j];
                            
            if (x == -1) {B[j] = i; break;} else re3(k, q0, n0) A[i][k] ^= A[x][k];
                        }
                        
            if (q1 == KS - 1) {q0++; q1 = 0;} else q1++;
                    }
                }
                q0 
            = n0; q1 = q;
                rre(i, n) {
                    
            if (q1) q1--else {q0--; q1 = KS - 1;}
                    
            if ((x = B[i]) >= 0) {
                        res[i] 
            = A[x][n0] & (1 << q);
                        re(j, n) 
            if (j != x && (A[j][q0] & (1 << q1))) {
                            A[j][q0] 
            ^= A[x][q0]; if (q0 < n0) A[j][n0] ^= A[x][n0];
                        }
                    } 
            else {
                        res[i] 
            = 1;
                        re(j, n) 
            if (A[j][q0] & (1 << q1)) {
                            A[j][q0] 
            &= ~(1 << q1); A[j][n0] ^= 1 << q;
                        }
                    }
                }
                re(i, n) 
            if ((x = B[i]) >= 0) C[x] = 1;
                re(i, n) 
            if (!C[i] && (A[i][n0] & (1 << q))) {res_ex = 0return;}
            }
            void pri()
            {
                freopen(
            "arc.out""w", stdout);
                
            if (res_ex) {
                    
            int sum = 0bool SPC = 0; re(i, n) if (!res[i]) sum++;
                    printf(
            "%d\n", sum);
                    re(i, n) 
            if (!res[i]) {
                        
            if (SPC) putchar(' '); else SPC = 1;
                        printf(
            "%d", i + 1);
                    }
                    puts(
            "");
                } 
            else puts("Impossible");
                fclose(stdout);
            }
            int main()
            {
                init();
                solve();
                pri();
                
            return 0;
            }

            Feedback

            # re: XOR專題(一):異或方程組的解法  回復(fù)  更多評(píng)論   

            2012-05-20 15:10 by lx99410
            你有JSOI2012題目與數(shù)據(jù)嗎?,能否發(fā)給我?郵箱:lixiang99410@126.com,不勝感激!

            # re: XOR專題(一):異或方程組的解法  回復(fù)  更多評(píng)論   

            2012-05-22 17:00 by olyminfo
            同求

            olyminfo@gmail.com

            # re: XOR專題(一):異或方程組的解法  回復(fù)  更多評(píng)論   

            2012-06-20 12:38 by wrz
            同求
            參加了,但是忘了拷了
            wrz_10@126.com

            # re: XOR專題(一):異或方程組的解法  回復(fù)  更多評(píng)論   

            2014-06-09 00:24 by AHdoc
            您應(yīng)該自豪的告訴別人: (1)這個(gè)題目是2010年合肥一中&蕪湖安師大附中友誼賽的題目..(2)被傻逼的AHdoc出到JSOI去了..=_=
            色欲久久久天天天综合网| 波多野结衣中文字幕久久| 国产成人久久久精品二区三区| 久久精品无码一区二区三区免费 | 久久精品无码一区二区三区免费 | 久久午夜福利无码1000合集| 久久黄色视频| 久久99精品国产麻豆宅宅| 国内精品久久久久久久coent| 久久免费视频6| 久久精品国产福利国产秒| 国产成人精品久久一区二区三区av | 国产亚洲美女精品久久久久狼| 久久99国产精品久久99| 久久久久久一区国产精品| 久久99精品国产麻豆宅宅| 欧美粉嫩小泬久久久久久久 | 久久久久国产精品麻豆AR影院| 香蕉aa三级久久毛片| 国产精品日韩深夜福利久久| 国产精品久久久久久久app| 国产精品一久久香蕉国产线看观看 | 国产成人精品久久亚洲高清不卡| 久久综合九色综合久99| 久久午夜伦鲁片免费无码| 精品免费久久久久国产一区 | 一本色道久久综合狠狠躁篇| 国产精品99久久久久久董美香 | 国产激情久久久久久熟女老人| 污污内射久久一区二区欧美日韩 | 精品少妇人妻av无码久久| 欧美久久精品一级c片片| 久久亚洲精精品中文字幕| 久久久精品久久久久久| 久久亚洲精品中文字幕三区| 日本WV一本一道久久香蕉| 亚洲精品无码久久久| 人人狠狠综合久久亚洲高清| 91精品国产综合久久四虎久久无码一级| 久久久久久精品成人免费图片 | 久久亚洲国产午夜精品理论片 |