jzoj P1966 棋盘游戏

83 篇文章 0 订阅
20 篇文章 0 订阅

题目大意

给定一个N*M的棋盘,每个格子里最多只可以放置一个棋子,求有多少种放置方案使得任意2*2的正方形区域内恰有2个棋子。

数据规模
对于30%的数据 N,M<=20
对于100%的数据 N,M<=10000

题解:

找规律+高精度:
答案就是2^M+2^N-2
公式推理:
首先我们对于这题,可以分析一下发现,
只要任意2行确定了任意2列确定了,那么整个矩形必定被确定下来了,此时就是一种方案数。
那么任意两列与任意两行共有多少种放法呢?
我们继续推:
假如就是前2行前2列:
对于前2行,我们发现取一列出来看一下:
1为放棋/0为不放
对于一组
0
1
我们如果要在它后面填棋子并且要满足,就必须要是
1 ···· 0
0 亦或者是 1,
对于一组
1
0
也是同理,所以填满前2行有2^M方式,但是因为
对于一种情况
0 0
1 1
这时候你必定就会有2列被固定,因为方案就被固定了,
而仅有
1 0 1 …… ·· 0 1 0
0 1 0 …… 或者 1 0 1不会被固定
所以此时被固定的方案有2^M-2种
然后我们单独考虑上述2种情况,
而你现在对于前2列,3到n行并不确定,
考虑0 1 或 1 0下面可以有2^(n-2)种放法,
因为有0 1 跟 1 0两种 所以有2^(n-1)种
因为有2个0 1 跟 2个1 0 所以有2^N种
因此,公式就是2^N+2^M-2
而因为数据所以套一下高精度就可以了。
如果你想优美那么你可以试试压位~

代码:

const
     maxn=10000;

var
     a,b,c:array [0..maxn+1] of longint;
     lena,lenb,lenc,i,j,x,n,m:longint;

begin
     assign(input,'chess.in'); reset(input);
     assign(output,'chess.out'); rewrite(output);
     readln(n,m);
     lena:=1;
     a[1]:=1;
     for i:=1 to n do
       begin
            x:=0;
            for j:=1 to lena do
              begin
                 a[j]:=a[j]*2+x;
                 x:=a[j] div 10;
                 a[j]:=a[j] mod 10;
              end;
            a[lena+1]:=x;
            if a[lena+1]>0 then inc(lena);
       end;
     lenb:=1;
     b[1]:=1;
     for i:=1 to m do
       begin
            x:=0;
            for j:=1 to lenb do
              begin
                   b[j]:=b[j]*2+x;
                   x:=b[j] div 10;
                   b[j]:=b[j] mod 10;
              end;
            b[lenb+1]:=x;
            if b[lenb+1]>0 then inc(lenb);
       end;
     a[1]:=a[1]-2;
     i:=1; x:=0;
     while (i<=lena) or (i<=lenb) do
        begin
              c[i]:=a[i]+b[i]+x;
              x:=c[i] div 10;
              c[i]:=c[i] mod 10;
              i:=i+1;
        end;
    if x>0 then
       begin
            lenc:=i;
            c[i]:=x;
       end
       else lenc:=i-1;
    for i:=lenc downto 1 do write(c[i]);
    close(input); close(output); 
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值