【NOIP提高组】数格子

20 篇文章 0 订阅
5 篇文章 0 订阅

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

以前做过一道经典题目和这题类似:铺砖块
很明显就是一道状压DP题目,把图形旋转成N*4的矩阵,复杂度显然就是 O(N24) ,但是发现N很大,那么就要用矩阵乘法了。在普通状压中,我们会处理出一个 2424 的二维数组,该数组表示从i状态能否转移到j状态,能为1,不能为0,这个矩阵就是转移矩阵,然后快速幂解决。

Code

var
    f:array[0..40,0..16,0..16] of int64;
    c:array[0..40] of longint;
    a,z:array[0..16] of int64;
    n,m,i,j,k,s:longint;
    sum:int64;
function pd(x:longint):boolean;
var sum:longint;
begin
    sum:=0;
    while x>0 do
    begin
        if x mod 2=0 then
        begin
            if sum mod 2=1 then exit(false);
            sum:=0;
        end else inc(sum);
        x:=x div 2;
    end;
    if sum mod 2=1 then exit(false) else exit(true);
end;
procedure doit;
var i,j,k:longint;
begin
    s:=1;c[1]:=1;sum:=1;
    while sum*2<=n do
    begin
        sum:=sum*2;
        inc(s);
        fillchar(f[s],sizeof(f[s]),0);
        c[s]:=c[s-1]*2;
        for i:=0 to 15 do
            for j:=0 to 15 do
                for k:=0 to 15 do
                f[s,i,j]:=(f[s,i,j]+f[s-1,i,k]*f[s-1,k,j] mod m)mod m;
    end;
end;
procedure deal(x:longint);
var i,j,k:longint;
begin
    for i:=0 to 15 do if pd(i) then a[i]:=1 else a[i]:=0;
    dec(x);
    i:=s;
    while x>0 do
    begin
        while c[i]>x do dec(i);
        fillchar(z,sizeof(z),0);
        for j:=0 to 15 do
            for k:=0 to 15 do
            z[j]:=(z[j]+a[k]*f[i,k,j])mod m;
        a:=z;
        x:=x-c[i];
    end;
end;
begin
    for i:=0 to 15 do
        for j:=0 to 15 do
        if pd(i+j) and((i and j)=0) then f[0,i,j]:=1;
    readln(n,m);
    while m<>0 do
    begin
        f[1]:=f[0];
        doit;
        deal(n);
        writeln(a[0]);
        readln(n,m);
    end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值