zoukankan      html  css  js  c++  java
  • BZOJ 4417 [Shoi2013]超级跳马

    首先,(dp[i][j])表示到(i)(j)列的方案数,则显然可以写出状态转移方程:

    [dp[i][j] = sum_{k = 1}^{(m + 1) / 2} dp[2 * k - 1][j - 1] + dp[2 * k - 1][j] + dp[2 * k - 1][j + 1] ]

    (2 * k - 1)这个东西不是很优美啊(这玩意怎么构造矩阵……),考虑把奇数(i)和偶数(i)分开考虑,(dp[0][i][j])为到(2 * i)(j)列的方案数,(dp[1][i][j])为到(2 * i - 1)(j)列的方案数。那么,就得到了两个更清真的(转移来自的状态是连续的,而不是一个隔一个)的状态转移方程:

    [dp[0][i][j] = sum_{k = 1}^{(m + 1) / 2} dp[1][k][j - 1] + dp[1][k][j] + dp[1][k][j + 1] ]

    [dp[1][i][j] = sum_{k = 1}^{(m + 1) / 2} dp[0][k - 1][j - 1] + dp[0][k - 1][j] + dp[0][k - 1][j + 1] ]

    这个东西还是很难变成矩阵,因为显然矩阵开不了(m)那么大……

    发现等式右边就是一个前缀和嘛!那么,设

    [f[0/1][i][j] = sum_{k = 1}^{i} dp[0/1][k][j] ]

    那么有:

    [f[1][i][j] = f[1][i - 1][j] + f[0][i - 1][j - 1] + f[0][i - 1][j] + f[0][i - 1][j + 1] ]

    [f0][i][j] = f[0][i - 1][j] + f[1][i][j - 1] + f[1][i][j] + f[1][i][j + 1] ]

    这个就可以构造矩阵了!

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define enter putchar('
    ')
    #define space putchar(' ')
    template <class T>
    void read(T &x){
        char c;
        bool op = 0;
        while(c = getchar(), c > '9' || c < '0')
    	if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
    	x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x){
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    
    const int N = 102, P = 30011;
    int n, m;
    struct matrix {
        int g[N][N];
        matrix(){
    	memset(g, 0, sizeof(g));
        }
        matrix(int useless){
    	for(int i = 0; i < n; i++)
    	    for(int j = 0; j < n; j++)
    		g[i][j] = (i == j);
        }
        matrix operator * (const matrix &b){
    	matrix c;
    	for(int k = 0; k < n; k++)
    	    for(int i = 0; i < n; i++)
    		for(int j = 0; j < n; j++)
    		    c.g[i][j] = (c.g[i][j] + g[i][k] * b.g[k][j]) % P;
    	return c;
        }
        void out(){
    	for(int i = 0; i < n; i++)
    	    for(int j = 0; j < n; j++)
    		write(g[i][j]), j == n - 1 ? enter: space;
    	enter;
        }
    } ans, op1, op2;
    
    matrix qpow(matrix a, int x){
        matrix ret(1);
        while(x){
    	if(x & 1) ret = ret * a;
    	a = a * a;
    	x >>= 1;
        }
        return ret;
    }
    int mod(int x){
        return (x % P + P) % P;
    }
    
    int main(){
    
        read(n), read(m);
        ans.g[0][0] = 1;
        for(int i = 0; i < n; i++){
    	if(i) op1.g[i + n][i - 1] = op2.g[i][i + n - 1] = 1;
    	op1.g[i + n][i] = op1.g[i + n][i + n] = op2.g[i][i + n] = op2.g[i][i] = 1;
    	if(i + 1 < n) op1.g[i + n][i + 1] = op2.g[i][i + n + 1] = 1;
    	op1.g[i][i] = op2.g[i + n][i + n] = 1;
        }
        n *= 2;
        ans = qpow(op2 * op1, m / 2 - 1) * ans;
        if(m & 1) write(mod((op2 * op1 * ans).g[n / 2 - 1][0] - ans.g[n / 2 - 1][0])), enter;
        else write(mod((op2 * op1 * ans).g[n - 1][0] - ans.g[n - 1][0])), enter;
    
        return 0;
    }
    
  • 相关阅读:
    JavaEE——SpringMVC(11)--拦截器
    JavaEE——SpringMVC(10)--文件上传 CommonsMultipartResovler
    codeforces 460A Vasya and Socks 解题报告
    hdu 1541 Stars 解题报告
    hdu 1166 敌兵布阵 解题报告
    poj 2771 Guardian of Decency 解题报告
    hdu 1514 Free Candies 解题报告
    poj 3020 Antenna Placement 解题报告
    BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
    poj 1325 Machine Schedule 解题报告
  • 原文地址:https://www.cnblogs.com/RabbitHu/p/BZOJ4417.html
Copyright © 2011-2022 走看看