zoukankan      html  css  js  c++  java
  • [hdu5411 CRB and Puzzle]DP,矩阵快速幂

    题意:给一个有向图,从任意点开始,最多走m步,求形成的图案总数。

    思路:令dp[i][j]表示走j步最后到达i的方法数,则dp[i][j]=∑dp[k][j-1],其中k表示可以直接到达i的点,答案=∑dp[i][j]。关键在于如何减少状态转移的时间,考虑用矩阵加速。

    构造矩阵:D = ,其中a[i][j]表示有向图,用于状态转移,右边的一列1用于累加答案

    则答案=[1,1,...1n+1]*DM-1=∑∑DM-1[i][j],1≤i≤n+1,1≤j≤n+1

    PS:封装的ModInt放矩阵的最里面进行运算比直接取模慢了3倍多,因此在性能瓶颈地方尽量用最快的写法

    #pragma comment(linker, "/STACK:10240000")
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define copy(a, b)          memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    #ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    #endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    
    const double PI = acos(-1.0);
    const int INF = 1e9 + 7;
    const double EPS = 1e-12;
    
    /* -------------------------------------------------------------------------------- */
    
    const int maxn = 51;
    
    template<int mod>
    struct ModInt {
        const static int MD = mod;
        int x;
        ModInt(ll x = 0): x(x % MD) {}
        int get() { return x; }
    
        ModInt operator + (const ModInt &that) const { int x0 = x + that.x; return ModInt(x0 < MD? x0 : x0 - MD); }
        ModInt operator - (const ModInt &that) const { int x0 = x - that.x; return ModInt(x0 < MD? x0 + MD : x0); }
        ModInt operator * (const ModInt &that) const { return ModInt((long long)x * that.x % MD); }
        ModInt operator / (const ModInt &that) const { return *this * that.inverse(); }
    
        ModInt operator += (const ModInt &that) { x += that.x; if (x >= MD) x -= MD; }
        ModInt operator -= (const ModInt &that) { x -= that.x; if (x < 0) x += MD; }
        ModInt operator *= (const ModInt &that) { x = (long long)x * that.x % MD; }
        ModInt operator /= (const ModInt &that) { *this = *this / that; }
    
        ModInt inverse() const {
            int a = x, b = MD, u = 1, v = 0;
            while(b) {
                int t = a / b;
                a -= t * b; std::swap(a, b);
                u -= t * v; std::swap(u, v);
            }
            if(u < 0) u += MD;
            return u;
        }
    
    };
    typedef ModInt<2015> mint;
    
    int N;
    struct Matrix {
        int a[maxn][maxn];
    
        Matrix() {
            for (int i = 0; i < N; i ++) {
                for (int j = 0; j < N; j ++) {
                    a[i][j] = 0;
                }
            }
        }
    
        static Matrix unit() {
            Matrix ans;
            for (int i = 0; i < N; i ++) ans.a[i][i] = 1;
            return ans;
        }
    
        Matrix &operator * (const Matrix &that) const {
            static Matrix ans;
            for (int i = 0; i < N; i ++) {
                for (int j = 0; j < N; j ++) {
                    ans.a[i][j] = 0;
                    for (int k = 0; k < N; k ++) {
                        ans.a[i][j] += a[i][k] * that.a[k][j];
                        ans.a[i][j] %= 2015;
                    }
                }
            }
            return ans;
        }
    
        static Matrix power(Matrix a, int n) {
            Matrix ans = unit(), buf = a;
            while (n) {
                if (n & 1) ans = ans * buf;
                buf = buf * buf;
                n >>= 1;
            }
            return ans;
        }
    };
    
    class Timer {
    private:
        clock_t _start;
        clock_t _end;
    
    public:
        void init() {
            _start = clock();
        }
        void get() {
            _end = clock();
            cout << double(_end - _start) / CLK_TCK << endl;
        }
    };
    Timer clk;
    
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int T, n, m, k, x;
        cin >> T;
        while (T --) {
            cin >> n >> m;
            Matrix a;
            N = n + 1;
            for (int i = 0; i < n; i ++) {
                scanf("%d", &k);
                for (int j = 0; j < k; j ++) {
                    scanf("%d", &x);
                    a.a[i][-- x] = 1;
                }
            }
            for (int i = 0; i < N; i ++) a.a[i][N - 1] = 1;
            Matrix A = Matrix::power(a, m - 1);
            mint ans = 0;
            for (int i = 0; i < N; i ++) {
                for (int j = 0; j < N; j ++) {
                    ans += A.a[i][j];
                }
            }
            cout << ans.get() << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    浙大数据结构课后习题 练习二 7-2 Reversing Linked List (25 分)
    浙大数据结构课后习题 练习二 7-2 一元多项式的乘法与加法运算 (20 分)
    浙大数据结构课后习题 练习一 7-1 Maximum Subsequence Sum (25 分)
    浙大数据结构课后习题 练习一 7-1 最大子列和问题 (20 分)
    PAT Basic 1019 数字黑洞 (20 分)
    PAT Basic 1017 A除以B (20 分)
    PAT Basic 1013 数素数 (20 分)
    PAT Basic 1007 素数对猜想 (20 分)
    PAT Basic 1003 我要通过! (20 分)
    自动化运维——HelloWorld(一)
  • 原文地址:https://www.cnblogs.com/jklongint/p/4746679.html
Copyright © 2011-2022 走看看