考拉 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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值