考拉 PASCAL 解題報告

考拉

 

從前,在一片美麗的樹林裏,居住着一隻可愛的小考拉。一天,小狐狸在OJ上刷題的時候遇到了這樣一個問題:

給定一個NM列的網格,請在每一格上填上+1或-1,使得每行和每列的數的乘積都等於-1。求方案數。

小狐狸不會做於是找到了小考拉。小考拉也不會做。你能幫助他麼?

 

輸入

有多組數據。輸入數據第一行包含T爲數據組數。

下面T行每行依次包含兩個整數NM

 

輸出

輸出T行每行一個整數,爲方案數。注意方案數可能很大。

 

樣例輸入

2

2 3

2 2

 

樣例輸出

0

2

 

數據範圍

對於20%的數據有1 ≤ N, M ≤ 5

對於100%的數據有1 ≤ N, M ≤ 100, 1 ≤ T ≤ 10

 

 

一開始就往動歸方面想。

但情況好多,於是寫了個簡單搜索程序,打了下面的表。

 

 

1

2

3

4

5

6

7

8

1

1

0

1

0

1

0

1

0

2

0

2

0

8

0

32

0

128

3

1

0

16

0

256

0

4096

 

4

0

8

0

512

0

32768

0

 

5

1

0

256

0

66536

0

 

 

6

0

32

0

32768

0

 

 

 

7

1

0

4096

0

 

 

 

 

8

0

128

 

 

 

 

 

 

 然後發現全都是2的次方,於是把錶轉化爲下面

 

1

2

3

4

5

6

7

8

1

0

1

0

1

0

1

0

1

2

1

1

1

3

1

5

1

7

3

0

1

4

1

8

1

12

 

4

1

3

1

9

1

15

1

 

5

0

1

8

1

16

1

 

 

6

1

5

1

15

1

 

 

 

7

0

1

12

1

 

 

 

 

8

1

7

 

 

 

 

 

 

 

不難看出,對於x=y=n 則 表2[x,y] = (n-1)^2。且對於x+y=2n 的數,其值都和 表2[n,n] 有關係 。所以就有了遞歸關係式。

 

這題還要用到高精度。最後的結果是個非常大的數。我一開始高精度數組開100,爆了;開到1000,又爆了;直到開到5000纔沒爆。

 

做是做出來了,但是不知道原因。。這大概就是考試時做動歸題目的策略。

 

 

                                              考拉 <wbr>PASCAL <wbr>解題報告

 正解:

考慮前N-1行M-1列隨便填,那麼第N行的前M-1列所有位置唯一確定,第M列的前N-1行所有位置也唯一確定。

如右圖。

這時分四種情況:

 

N爲奇數,M爲奇數,則區域2的格子的乘積等於的區域1的乘積,區域3的乘積同樣等於的區域1的乘積,而區域四的乘積等於區域2的乘積等於區域3的乘積,於是此時答案唯一。

N爲奇數,M爲偶數,則區域2的格子的乘積等於的區域1的乘積,區域3的乘積卻等於的區域1的乘積,此時區域2的乘積不等於區域3的乘積,無解。

N爲偶數,M爲偶數,同理可知解唯一。

N爲偶數,M爲奇數,同理可知無解。

 

綜上可知,若NM奇偶性相同則答案爲2(N-1)*(M-1),否則答案爲0。



 

var
 t,n,m,k,o,key,oo,i,j:longint;
 a:array[0..5000]of longint;

procedure cheng;
var
 g,i:longint;
begin
 g:=0;
 for i:=5000 downto a[0] do
  begin
   a[i]:=a[i]+a[i]+g;
   g:=a[i] div 10;
   a[i]:=a[i] mod 10;
  end;
 if g<>0 then
   begin
   dec(a[0]);
   a[a[0]]:=g;
   end;
end;

begin
 assign(input,'koala.in');
 assign(output,'koala.out');
 reset(input);
 rewrite(output);
 read(t);
 while t>0 do
  begin
  dec(t);
  read(n,m);
  k:=m+n;
  if k mod 2<>0 then begin writeln(0); continue; end;
  o:=k div 2-1;
  key:=o*o;
  o:=o+1;
  if (o=n)or(o=m) then oo:=key
                  else oo:=key-abs(o-m)*abs(o-m);

  fillchar(a,sizeof(a),0);
  a[5000]:=1;
  a[0]:=5000;
  while oo>0 do
   begin
   cheng;
   dec(oo);
   end;
  i:=1;
  for j:=a[0] to 5000 do write(a[j]);
  writeln;
  end;
  close(input);
  close(output);
end.5

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章