zoukankan      html  css  js  c++  java
  • Luogu 4159 [SCOI2009]迷路

    BZOJ 1297

    应当是简单题。

    发现边权的数量很小,所以我们暴力把一个点拆成$9$个点,然后把$(x, i)$到$(x, i + 1)$连边,代表转移一次之后可以走回来;对于每一条存在的边$(i, j, k)$,把$(i, k)$向$(j, 1)$连边,代表走一条路。然后用这个矩阵乘$T$次即可,这样子最后的答案$ans = [(1, 1)][(n, 1)]$格子的值。

    记$m = 9 * n$,时间复杂度为$O(m^3logT)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 15;
    const int M = 105;
    const int P = 2009;
    
    int n, tim;
    
    inline void inc(int &x, int y) {
        x += y;
        if(x >= P) x -= P;
    }
    
    inline int id(int x, int k) {
        return (x - 1) * 9 + k;
    }
    
    struct Matrix {
        int len, wid, s[M][M];
    
        inline void init(int r, int c) {
            len = r, wid = c;
            memset(s, 0, sizeof(s));
        } 
    
        friend Matrix operator * (const Matrix &x, const Matrix &y) {
            Matrix res; res.init(x.len, y.wid);
            for(int k = 1; k <= x.wid; k++)
                for(int i = 1; i <= x.len; i++)
                    for(int j = 1; j <= y.wid; j++)
                        inc(res.s[i][j], x.s[i][k] * y.s[k][j] % P);
            return res;
        }
    
        inline void print() {
            for(int i = 1; i <= len; i++, printf("
    "))
                for(int j = 1; j <= wid; j++)
                    printf("%d ", s[i][j]);
        }
    
    } f;
    
    inline Matrix fpow(Matrix x, int y) {
        Matrix res; res.init(x.len, x.wid);
        for(int i = 1; i <= x.len; i++) res.s[i][i] = 1;
        for(; y > 0; y >>= 1) {
            if(y & 1) res = res * x;
            x = x * x;
        }
        return res;
    }
    
    int main() {
        scanf("%d%d", &n, &tim);
        f.init(9 * n, 9 * n);
        for(int i = 1; i <= n; i++) {
            char str[N];
            scanf("%s", str + 1);
            for(int j = 1; j <= n; j++) {
                int k = str[j] - '0';
                if(!k) continue;
                f.s[id(i, k)][id(j, 1)] = 1;
            }
    
            for(int j = 2; j <= 9; j++)
                f.s[id(i, j - 1)][id(i, j)] = 1;
        }
    
    //    f.print();
    
        f = fpow(f, tim);
     //   f.print();
    
        printf("%d
    ", f.s[id(1, 1)][id(n, 1)]);
        return 0;
    }
    View Code
  • 相关阅读:
    2014年互联网发展趋势如何
    服务器出现阶段性错误
    用互联网思想武装自己
    杭州互联网公司汇总
    互联网牛人网址大全
    ffmpeg开发指南
    Windows下FFmpeg快速入门
    FFmpeg介绍及参数详细说明
    windows 下FFMPEG的编译方法 附2012-9-19发布的FFMPEG编译好的SDK下载
    FFMPEG视音频编解码零基础学习方法 【荐】
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9824031.html
Copyright © 2011-2022 走看看