zoukankan      html  css  js  c++  java
  • jzoj3294. 【SHTSC2013】超级跳马

    Description

    在这里插入图片描述

    Input

    仅有一行,包含两个正整数n, m,表示棋盘的规模。

    Output

    仅有一行,包含一个整数,即跳法种数mod 30011。

    Sample Input

    3 5

    Sample Output

    10

    Data Constraint

    对于10%的数据,1 ≤ n ≤ 10,2 ≤ m ≤ 10;
    对于50%的数据,1 ≤ n ≤ 10,2 ≤ m ≤ 10^5;
    对于80%的数据,1 ≤ n ≤ 10,2 ≤ m ≤ 10^9;
    对于100%的数据,1 ≤ n ≤ 50,2 ≤ m ≤ 10^9。

    题解

    比赛时心态崩了没有调出来,血亏。
    我还是太蔡了。
    10%
    我们考虑DP。设f[i,j]f_{[i,j]}表示走到(i,j)(i,j)这个位置的方案数。
    O(nm2)O(n*m^2)暴力转移。
    50%
    我们发现,上面的时间复杂度实在太大。
    怎么办?我们发现转移的时候j都是奇偶列交替枚举的。
    于是我们可以利用前缀和优化来分别记录奇数列与偶数列。
    O(nm)O(n*m)
    100%
    我们发现,m极其的大。
    那么很容易想到矩阵。
    但是我们的转移是奇偶列交替来搞的。
    这很难直接转移。
    一个直观的想法——由于是交替来搞,我们直接把奇列与偶列连在一起,变成下图:
    在这里插入图片描述
    那么,我们发现,由于偶列是不变的,奇列是转移过去的。
    那么我们的转移矩阵就很好推了。
    首先,由于新的偶列与奇列都是继承原来的,所以说,右上与左下都是1矩阵(a[i,i]=1a[i,i]=1
    然后,由于转移的新奇列是要与偶列进行DP的,所以左上是一个dp矩阵(很好推)
    但是新的奇列与原来的奇列是不dp的,所以右下是什么都没有的。
    直接快速幂即可。

    标程

    type
            arr=array[1..100,1..100] of int64;
    var
            i,j,k,l,n,m,r,p,ans1,ans2:longint;
            mo:int64=30011;
            a,b,jl:arr;
    function qsm(a,b:int64):int64;
    var
            t,y:int64;
    begin
            t:=1;
            y:=a;
            while b>0 do
            begin
                    if b mod 2=1 then t:=t*y mod mo;
                    y:=y*y mod mo;
                    b:=b div 2;
            end;
            exit(t);
    end;
    function cheng(a,b:arr;p:longint):arr;
    var
            i,j,k:longint;
    begin
            fillchar(cheng,sizeof(cheng),0);
            for i:=1 to p do
            begin
                    for j:=1 to p do
                    begin
                            for k:=1 to p do
                            begin
                                    cheng[i,j]:=(cheng[i,j]+a[i,k]*b[k,j]) mod mo;
                            end;
                    end;
            end;
            exit(cheng);
    end;
    function ksm(a:arr;b:int64):arr;
    var
            t,y:arr;
    begin
            t:=a;
            y:=a;
            dec(b);
            while b<>0 do
            begin
                    if(b and 1)=1 then
                            t:=cheng(t,y,p);
                    y:=cheng(y,y,p);
                    b:=b shr 1;
            end;
            exit(t);
    end;
    begin
            //assign(input,'0data.in');reset(input);
            //assign(output,'0data.out');rewrite(output);
            readln(n,m);
            p:=2*n;
            for i:=1 to n do
            begin
                    a[i,i]:=1;
                    if i>1 then
                    begin
                            a[i-1,i]:=1;
                            a[i,i-1]:=1;
                    end;
            end;
            for i:=1 to n do
            begin
                    a[i+n,i]:=1;
                    a[i,n+i]:=1;
            end;
            m:=m-1;
    
            jl:=a;
            b:=ksm(jl,m);
            fillchar(a,sizeof(a),0);
            a[1,1]:=1;
            b:=cheng(a,b,p);
            if n=1 then
            begin
                    writeln(b[1,n*2]);
                    halt;
            end;
            writeln((b[1,n*2]+b[1,n*2-1]) mod mo);
    end.
    end.
    
    
    
  • 相关阅读:
    Pentaho
    知识地图
    分享学习笔记本
    2015-7-1 记而随,随而记
    web 导出 csv
    vs2013 密钥
    超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
    如何绘制业务流程图?
    总是保存下拉选项的第一个值
    mac 修改密码后 频繁输入钥匙串问题修复方法
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148350.html
Copyright © 2011-2022 走看看