hihoCoder1196 高斯消元

2022-05-29 08:06:08 字數 3632 閱讀 1800

時間限制:10000ms

單點時限:1000ms

記憶體限制:256mb

描述在上一回中,小hi和小ho趁著便利店打折,買了一大堆零食。當他們結賬後,看到便利店門口還有其他的活動。

店主:買了東西還可以參加遊戲活動哦,如果能夠完成遊戲還有額外的獎品。

小hi和小ho趕緊湊了過去。

店主放了一塊遊戲板在店門口,有5行6列格仔。左上角為座標(1,1)。一部分格仔是亮著的,另一部分是暗著的。

當按下某乙個格仔時,它和上下左右4個格仔的狀態就會改變。原來亮著的格仔變成暗的,原來暗的格仔會變亮。比如下圖中按下標記有紅叉的格仔後,綠色虛線區域內的格仔狀態都會改變:

店主給出初始的狀態,參加遊戲的人員需要通過按下某些格仔,讓遊戲板上所有的燈都亮起來就可以贏得獎品。

小ho:這不就是開關燈問題麼,看我來解決它!

小ho在遊戲板上忙碌了30分鐘,任然沒有辦法完成,於是他只好求助於小hi。

小ho:小hi,這次又該怎麼辦呢?

小hi:讓我們來分析一下吧。

首先對於每乙個格仔的狀態,可能會對它造成影響的是其自身和周圍4個格仔,這五個格仔被按下的總次數也就等於該格仔所改變的總次數。

對於任意乙個格仔,如果這個格仔改變了偶數次狀態,則等價於沒有發生改變。

我們可以將1看作格仔亮著,0看作格仔暗著,每改變1次就加1,最後格仔的狀態等於其總數值 mod 2。

則其運算結果剛好滿足異或運算,即每改變一次等於狀態值 xor 1。

假設有陣列x[1..30],分別表示這30個格仔是否按下1次,若按下則x[i]=1,否則x[i]=0。

則對於1個格仔,他最後的狀態為:

當前狀態 = 初始狀態 xor (a[1] * x[1]) xor (a[2] * x[2]) xor ... xor (a[30] * x[30])
其中a[i]表示格仔i是否會對當前格仔產生影響,若能夠則a[i] = 1,否則a[i] = 0

對方程進行變換有:

(a[1] * x[1]) xor (a[2] * x[2]) xor ... xor (a[30] * x[30]) = 當前狀態 xor 初始狀態
因為我們的目標是要讓所有等格仔都為亮的狀態,故我們需要讓 當前狀態 = 1,則:

(a[1] * x[1]) xor (a[2] * x[2]) xor ... xor (a[30] * x[30]) = 1 xor 初始狀態
不妨設y = 1 xor 初始狀態:

(a[1] * x[1]) xor (a[2] * x[2]) xor ... xor (a[30] * x[30]) = y
對於所有的格仔,我們可以連立出方程組:

(a[ 1][1] * x[1]) xor (a[ 1][2] * x[2]) xor ... xor (a[ 1][30] * x[30]) = y[ 1]

(a[ 2][1] * x[1]) xor (a[ 2][2] * x[2]) xor ... xor (a[ 2][30] * x[30]) = y[ 2]

...(a[30][1] * x[1]) xor (a[30][2] * x[2]) xor ... xor (a[30][30] * x[30]) = y[30]

到此,我們的目標就是求出乙個x[1..30],使得上面的方程組成立。

小ho:這個看上去和高斯消元很像啊。

小hi:沒錯,這個方程組叫異或方程組,它可以用和高斯消元同樣的方法來解決。

其解答過程幾乎和高斯消元無異,判定無解和多解的方式也相同。唯一需要注意的是消元過程不再是高斯消元的加減,而是通過xor運算來進行消元。比如消除第j行第i列的1:

a[j][k] = a[j][k] xor a[i][k], y[j] = y[j] xor y[i]
其原理是:

(a[j][1] * x[1]) xor (a[j][2] * x[2]) xor ... xor (a[j][30] * x[30]) xor (a[i][1] * x[1]) xor (a[i][2] * x[2]) xor ... xor (a[ i][30] * x[30]) = y[j] xor y[i]

<=> ((a[j][1] * x[1]) xor (a[i][1] * x[1])) xor (((a[j][2] * x[2]) xor (a[i][2] * x[2]))) xor ... xor ((a[j][30] * x[30]) xor (a[i][30] * x[30])) = y[j] xor y[i]

<=> ((a[j][1] xor a[i][1]) * x[1]) xor ((a[j][2] xor a[i][2]) * x[2]) xor ... ((a[j][30] xor a[i][30]) * x[30]) = y[j] xor y[i]

而且由於給定遊戲板是固定的,我們可以知道a[i][j]矩陣一定是固定的,而且通過計算可以知道我們消元得到的上三角矩陣也是固定的,並且在這一次的問題中該上三角矩陣是滿秩的,所以其一定存在唯一解。

所以我們一定有辦法完成這個遊戲。

小ho:我明白了,我這就去寫程式,這獎品我拿定了!

輸入第1..5行:1個長度為6的字串,表示該行的格仔狀態,1表示該格仔是亮著的,0表示該格仔是暗的。

保證一定存在解,且一定存在暗著的格仔。

輸出需要按下的格仔數量k,表示按下這k個位置後就可以將整個遊戲板所有的格仔都點亮。

接下來k行,每行乙個座標(x,y),表示需要按下格仔(x,y)。x座標較小的先輸出,若x相同,則先輸出y座標較小的。

樣例輸入

001111

011111

111111

111110

111100

樣例輸出

2

1 15 6

分析:上面的提示說的很清楚,建乙個30個未知數的方程組,

然後用高斯消元解方程,因為方程保證一定有解所以不用判斷無解的情況。

#include#include

#include

using

namespace

std;

int a[40][40

];int num[7][7

];int d[5][2]=;

void

guass()

for(int k=i+1;k<=n;k++)

}//從下往上消去

int ans=0

;

for(int i=n;i;i--)

}}int

main()

for(int i=1;i<=5;i++)

}guass();

int ans=0

;

for(int i=1;i<=30;i++) if(a[i][31]) ans++;

printf(

"%d\n

",ans);

for(int i=1;i<=30;i++)

return0;

}

view code

hiho 1196 高斯消元 二

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述在上一回中,小hi和小ho趁著便利店打折,買了一大堆零食。當他們結賬後,看到便利店門口還有其他的活動。店主 買了東西還可以參加遊戲活動哦,如果能夠完成遊戲還有額外的獎品。小hi和小ho趕緊湊了過去。店主放了一塊遊戲板在店門...

高斯消元 hihocoder 1195

include include include include include include include include include include include include include include include include define mt a,b memset a...

數論 HihoCoder1195 高斯消元

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述小ho 喂不得了啦,那邊便利店的薯片半價了 小hi 啥?小ho 那邊的便利店在打折 啊。小hi 走走走,趕緊去看看 v 於是小hi和小ho來到了便利店。老闆為了 推出了組合包的形式,將不同數量的各類商品打包成乙個組合,顧客...