zoukankan      html  css  js  c++  java
  • SHOI2013 超级跳马

    我是常年游荡于题解区的幽灵。

    直观的想法就是前缀和+差分优化DP, 但还有些比较奇妙的方法or trick:

    1. (f[i][j] = f[i-1][j-1]+f[i-1][j]+f[i-1][j+1]+color{red}{f[i-2][j]}), 因为可以一步跳到 (f[i][j]) 的状态也可以一步跳到 (f[i-2][j]), 反过来也成立 。

    2. 只考虑从左边某个特定的列的转移矩阵, 设为 (J), 设第 (i) 列的答案矩阵是 (A_i), 则有:(A_n = J*(A_{n-1}+A_{n-3}+A_{n-5}+cdots))(A_{n-2} = J*(A_{n-3}+A_{n-5}+A_{n-7}+cdots)), 不难得出 (A_n = J*A_{n-1}+A_{n-2}), 这也是个递推, 构造矩阵:

    [[ egin{matrix} J & E\ E & O end{matrix} ] * [ egin{matrix} A_n\ A_{n+1} end{matrix} ]=[ egin{matrix} A_{n+1}\ A_{n} end{matrix} ] ]

    其中 (E) 是单位矩阵而 (O) 是全零矩阵,就可以大力递推了。

    1. 这个, 建图

    接下来选择性地实现/口胡上述的某些解法(我挺中意矩阵套矩阵的解法)


    直观解法

    s0[i] 维护与当前列差偶数列的第 i 行的方案数之和, s1[i] 则是相差奇数列的。

    考虑转移到下一列, 则有:
    s0[i] <- s1[i] + s0[i-1] + s0[i] + s0[i+1]

    s1[i] <- s0[i]


    矩阵套矩阵

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int mo = 30011;
    int n,m;
    
    int qm(int x) { return x>=mo?x-mo:x; }
    
    struct M{
    	int t[51][51];
    	M() {memset(t,0,sizeof t);  }
    };
    M operator*(const M &a, const M &b) {
    	M c; for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)for(int k=1;k<=n;++k)
    			c.t[i][j] = qm(c.t[i][j] + a.t[i][k]*b.t[k][j]%mo);
    	return c;
    }
    M operator+(const M &a, const M &b) {
    	M c; for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
    			c.t[i][j] = qm(a.t[i][j] + b.t[i][j]);
    	return c;
    }
    
    struct M2{ M t[3][3]; } S,T,Delta;
    M2 operator*(const M2 &a, const M2 &b) {
    	M2 c; for(int i=1;i<=2;++i)for(int j=1;j<=2;++j)for(int k=1;k<=2;++k)
    			c.t[i][j]= c.t[i][j] + a.t[i][k]*b.t[k][j];
    	return c;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	S.t[1][1].t[1][1] = S.t[1][1].t[2][1] = 1;//µÚ¶þÁеĴ𰸾ØÕó
    	if(m==2) return printf("%d",S.t[1][1].t[n][1]),0;
    	for(int i=1;i<=n;++i) {
    		T.t[1][2].t[i][i] = T.t[2][1].t[i][i] = 1;
    		T.t[1][1].t[i][i-1] = T.t[1][1].t[i][i] =T.t[1][1].t[i][i+1] = 1;
    	}
    	m -= 3;
    	Delta = T;
    	while(m)
    	{
    		if(m&1) Delta = Delta * T;
    		T = T*T;
    		m >>= 1;
    	}
    	S = Delta*S;
    	printf("%d",S.t[1][1].t[n][1]);
    	return 0;
    }
    
  • 相关阅读:
    Interview with BOA
    Java Main Differences between HashMap HashTable and ConcurrentHashMap
    Java Main Differences between Java and C++
    LeetCode 33. Search in Rotated Sorted Array
    LeetCode 154. Find Minimum in Rotated Sorted Array II
    LeetCode 153. Find Minimum in Rotated Sorted Array
    LeetCode 75. Sort Colors
    LeetCode 31. Next Permutation
    LeetCode 60. Permutation Sequence
    LeetCode 216. Combination Sum III
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14034760.html
Copyright © 2011-2022 走看看