• [SRM613~] TaroCheckers


    一定要注意Topcoder的提交机制

    Links: 原题地址 Vjudge

    Solution

    这道题思维比较巧妙。 一看就基本知道是一个Dp题。

    首先转换一下,用列而不是行来设第一维的状态,因为每列只有放或不放两种状态。行的受力情况很复杂,这里啊

    那么对于每一列,到了要分配Left的时候我们再把前面的列分配过来。

    Right的时候,我们就反其道而行之,把Right贮存下来,然后之后每一个格子都考虑要不要分配一次。

    这样Dp状态就显而易见:(Dp[i][j][k])表示前i列中有j列空余kRight没有处理的方案数。

    然后就比较容易写出dp方程.下面是废话:

    先分类。这一列可以对Left Right造成影响. 也可以不造成影响(放在没用的地方或完全不让放)

    因为Left,Right对状态影响很大,所以分成两个式子。

    notice:在考虑问题的时候中间问题的中间态如果不是很重要的话,整体都可以略过

    具体见代码

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    typedef long long LL;
    typedef long double LD;
    int read() {
        char ch = getchar();
        int x = 0, flag = 1;
        for (;!isdigit(ch); ch = getchar()) if (ch == '-') flag *= -1;
        for (;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        return x * flag;
    }
    void write(int x) {
        if (x < 0) putchar('-'), x = -x;
        if (x >= 10) write(x / 10);
        putchar(x % 10 + 48);
    }
    
    const int Maxn = 59, Maxm = 209, Mod = 1e9 + 7;
    class TaroCheckers {
    	public:
    		LL C[Maxm * 10][Maxm * 10], dp[Maxm][Maxm][Maxn], fac[Maxm * 10];
    		LL L[Maxm], R[Maxm];
    		void calcMath(LL m) {
    			C[0][0] = fac[0] = 1;
    			rep (i, 1, m) fac[i] = fac[i - 1] * i % Mod;
    			rep (i, 1, m) {
    				C[i][0] = C[i][i] = 1;
    				rep (j, 1, i - 1) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % Mod;
    			}
    		}
    		int getNumber(vector <int> Left, vector <int> Right, int m) {
    			LL n = (LL)Left.size();
    			calcMath(n + m); clar(dp, 0); clar(L, 0), clar(R, 0);
    			rep (i, 0, n - 1) ++L[Left[i]], ++R[m - Right[i] + 1];
    			dp[0][0][0] = 1; LL res = 0;
    			rep (i, 0, m - 1) {
    				LL cnt1 = L[i + 1], cnt2 = R[i + 1];
    				rep (j, 0, i)
    					rep (k, 0, n)
    						if (dp[i][j][k]) {
    							if (j + 1 >= cnt1) (dp[i + 1][j + 1 - cnt1][k + cnt2] += dp[i][j][k] * C[j + 1][cnt1] % Mod * fac[cnt1] % Mod) %= Mod; 
    							if (j >= cnt1) (dp[i + 1][j - cnt1][k + cnt2] += dp[i][j][k] * C[j][cnt1] % Mod * fac[cnt1] * (res - cnt2 + 1) % Mod) %= Mod; 
    							if (j >= cnt1 && k + cnt2 - 1 >= 0) (dp[i + 1][j - cnt1][k + cnt2 - 1] += dp[i][j][k] * C[j][cnt1] % Mod * fac[cnt1] % Mod * (k + cnt2) % Mod) %= Mod;  
    						}
    				res += cnt1 - cnt2;
    			}
    
    			return dp[m][0][0];
    		}
    };
    
  • 相关阅读:
    BNU Online Judge-29140
    HDU-1022-Train Problem I
    HDU-1312-Red and Black
    BNU Online Judge-34978-汉诺塔
    BNU Online Judge-34976-数细菌
    BNU Online Judge-34973-Liserious战队
    HDU-1010-Tempter of the Bone
    HDU-1518-Square
    thinkphp笔记
    1210. 连号区间数
  • 原文地址:https://www.cnblogs.com/qrsikno/p/10159822.html
Copyright © 2020-2023  润新知