zoukankan      html  css  js  c++  java
  • [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];
    		}
    };
    
  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/qrsikno/p/10159822.html
Copyright © 2011-2022 走看看