• Codeforces Round #420 (Div. 2)


    题目链接:http://codeforces.com/contest/821/problem/E

    题意:起初在(0,0),现在要求走到(k,0),问你存在多少种走法。 其中有n条线段,每条线段为(a,y)->(b,y),代表如果x坐标走到[a,b]之间时,处于的y坐标要小于这个线段的y坐标,就是只能在线段的下方走(包括刚好在线段上),并且前一个段线段的x坐标与后一个线段的x坐标相同。

    思路:dp[i][j]代表从起点走到(i,j)时的走法,那么dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+dp[i-1][j+1]。由于dp[i]只由dp[i-1]转移过来,所以可以忽略i这一维,由于y坐标比较少,x坐标比较大,所以通过矩阵快速幂来优化。

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<queue>
    #include<vector>
    #include<time.h>
    #include<stack>
    #include<cmath>
    using namespace std;
    typedef long long int LL;
    const LL INF = 9223372036854775807;
    const int MAXN = 100 + 24;
    const int MAXX = 16 + 24;
    const int mod = 1e9 + 7;
    struct Node{
        LL l, r, y;
    }P[MAXN];
    struct Matrix{
        int row, col;
        LL m[MAXX][MAXX];
        void init(int row, int col){
            this->row = row;
            this->col = col;
            for (int i = 0; i < row; ++i)
                for (int j = 0; j < col; ++j)
                    m[i][j] = 0;
        }
    }C;
    Matrix operator*(const Matrix & a, const Matrix& b){
        Matrix res;
        res.init(a.row, b.col);
        for (int k = 0; k < a.col; ++k){
            for (int i = 0; i < res.row; ++i){
                if (a.m[i][k] == 0) continue;
                for (int j = 0; j < res.col; ++j){
                    if (b.m[k][j] == 0) continue;
                    res.m[i][j] = (a.m[i][k] * b.m[k][j] + res.m[i][j]) % mod;
                }
            }
        }
        return res;
    }
    Matrix operator+(const Matrix & a, const Matrix& b){
        Matrix res;
        res.init(a.row, b.col);
        for (int i = 0; i< a.col; ++i){
            for (int j = 0; j < res.row; ++j){
                res.m[i][j] = (a.m[i][j] + b.m[i][j]) % mod;
            }
        }
        return res;
    }
    Matrix Mpow(Matrix A, LL n){
        Matrix ans = A, p = A;
        while (n){
            if (n & 1){
                ans = ans*p; n--;
            }
            n >>= 1; p = p*p;
        }
        return ans;
    }
    int main(){
    //#ifdef kirito
    //    freopen("in.txt", "r", stdin);
    //    freopen("out.txt", "w", stdout);
    //#endif
    //    int start = clock();
        int n; LL k;
        while (~scanf("%d%lld",&n,&k)){
            for (int i = 0; i < n; i++){
                scanf("%lld%lld%lld", &P[i].l, &P[i].r, &P[i].y);
            }
            C.init(16, 1);  C.m[0][0] = 1; 
            for (int i = 0; i < n; i++){
                if (P[i].l >= k){
                    break;
                }
                Matrix res; res.init(16, 16);
                for (int j = 0; j < 16; j++){
                    if (j>P[i].y){
                        break;
                    }
                    for (int q = -1; q <= 1; q++){
                        if (j + q >= 0 && j + q <= P[i].y){
                            res.m[j][j + q] = 1;
                        }
                    }
                }
                res = Mpow(res, min(k,P[i].r) - min(k,P[i].l)-1); //超过k的不需计算
                for (int j = P[i].y + 1; j < 16; j++){ //超过线段y坐标的走法不存在,置0
                    C.m[j][0] = 0;
                }
                C = C*res;
            }
            printf("%lld
    ", C.m[0][0]);
        }
    //#ifdef LOCAL_TIME
    //    cout << "[Finished in " << clock() - start << " ms]" << endl;
    //#endif
        return 0;
    }
  • 相关阅读:
    Android&Java面试题大全—金九银十面试必备
    android招聘啦,美图秀秀欢迎你加入!
    android经典源码,很不错的开源框架
    MongoDB、Hbase、Redis等NoSQL优劣势、应用场景
    体验go语言的风骚式编程
    金九银十中,看看这31道Android面试题
    android高级页面效果集锦
    flask中的request
    flask笔记(三)Flask 添加登陆验证装饰器报错,及解析
    flask笔记(二)
  • 原文地址:https://www.cnblogs.com/kirito520/p/7094879.html
Copyright © 2020-2023  润新知