zoukankan      html  css  js  c++  java
  • bzoj 1297 矩阵乘法变形

    首先对于矩阵乘法的功能有很多,记得有篇论文叫矩阵乘法在信息学竞赛中的应用,里面详细介绍了矩阵的

    作用

    其中一个就是求图的固定时间方案数,也就是给定一张图,每两个点之间由一条边长为1的边相连,

    求任意两点之间的路径和为x的方案数

    论文很详细,这里只做简要的说明

    对于矩阵乘法,具体代码为

    for i:=1 to n do 
        for j:=1 to n do     
            for k:=1 to n do a[i,j]:=a[i,j]+b[i,k]*c[k,j];

    那么如果b矩阵,b[i,j]代表I到J,路径长为x的方案数,c[i,j]代表I到J,路径长为Y的方案数,那么k相当于中转点

    c[i,j]这样转移之后,根据加法原理,就代表I到J,路径长为X+Y的方案数,这样就可以转移了

    那么我们初始矩阵,ans[I,J]=1代表I,J之间有边(这里指有向边),将这个矩阵自乘X次得到的就是答案矩阵了,

    即ans[I,J]为I到J长为X的方案数

    那么对于这道题,他的路径长度可以为1-9,那么我们把一个点拆成一条有向链,然后假设连接I,J长度为3,

    就连I链中第3个点,J中第一个点,长度为1的边就行了

    /**************************************************************
        Problem: 1297
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:3128 ms
        Memory:348 kb
    ****************************************************************/
     
    //By BLADEVIL
    type
        rec                     =array[0..100,0..100] of longint;
         
    var
        n, t                    :longint;
        sum, ans                :rec;
     
    procedure init;
    var
        i, j                    :longint;
        len                     :longint;
        ss                      :char;
    begin
        readln(n,t);
        for i:=1 to n do
        begin
            for j:=1 to n do
            begin
                read(ss);
                len:=ord(ss)-48;
                if len=0 then continue;
                sum[(i-1)*9+len,(j-1)*9+1]:=1;
            end;
            readln;
        end;
        for i:=1 to n do
            for j:=0 to 7 do sum[(i-1)*9+1+j,(i-1)*9+j+2]:=1;
     
    end;
     
    function mul(a,b:rec):rec;
    var
        i, j, k                 :longint;
    begin
        fillchar(mul,sizeof(mul),0);
        for i:=1 to n*9 do
            for j:=1 to n*9 do
                for k:=1 to n*9 do mul[i,j]:=(mul[i,j]+a[i,k]*b[k,j]) mod 2009;
    end;
     
    procedure main;
    var
        p                       :longint;
        i, j                    :longint;
    begin
        for i:=1 to n*9 do ans[i,i]:=1;
        p:=t;
        while p<>0 do
        begin
            if p mod 2=1 then ans:=mul(sum,ans);
            sum:=mul(sum,sum);
            p:=p div 2;
        end;
        writeln(ans[1,(n-1)*9+1]);
    end;
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    【作业】Python
    【作业】判断某个数是否是素数,返回结果
    【案例】Python之列表反转
    Python模块
    【作业】Python-数据转换:将列表["mo","deng","ge"]和[1,2,3] 转换成[("mo",1),("deng",2),("ge",3)]
    【个人笔记】Python-zip()函数
    【作业】Python-数据转换:将列表[3,7,0,5,1,8]中大于5元素置为0,小于5的元素置为1
    【作业】Python-将元组(1,2,3) 和集合{"four",5,6}合成一个列表
    【作业】Python-函数封装:交换两个变量的值
    【个人笔记】Python-sorted()函数
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3472253.html
Copyright © 2011-2022 走看看