• JZOJ 5192. 【NOI2017模拟7.2】容器 (dp)


    https://gmoj.net/senior/#contest/show/2376/1

    题解:

    考虑把区间拆成左端点和右端点,(T)的限制相当于任何一个时候,没有匹配的左端点(le T)

    (f[i][p][q])表示刚刚确定了(i)的右括号,和(i+1)的左括号,匹配了(p)个区间,还有(q)左括号。

    转移可以枚举下一步选多少,顺便分配是那些跳蚤选了这些左括号和右括号就行了。

    一直纠结于用(frac{k!}{prod a[i]!})去计算分配方案,事实上不用,这样也做不了。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 1011110011;
    
    const int N = 45;
    
    int n, k, t;
    ll c[N][N];
    
    ll f[N][N][N];
    
    void add(ll &x, ll y) {
    	(x += y) %= mo;
    }
    
    int main() {
    	freopen("container.in", "r", stdin);
    	freopen("container.out", "w", stdout);
    	scanf("%d %d %d", &n, &k, &t);
    	fo(i, 0, 40) {
    		c[i][0] = 1;
    		fo(j, 1, i) c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mo;
    	}
    	f[0][0][0] = 1;
    	n ++;
    	fo(i, 1, n) {
    		fo(p, 0, k) fo(q, 0, k) if(f[i - 1][p][q]) {
    			fo(u, 0, q)	fo(v, 0, k - p - q) {
    				int np = p + u, nq = q - u + v;
    				if(np + nq > k || nq > t) continue;
    				add(f[i][np][nq], f[i - 1][p][q] * c[q][u] % mo * c[k - p - q][v]);
    			}
    		}
    	}
    	ll ans = f[n][k][0];
    	pp("%lld
    ", ans);
    }
    
    
  • 相关阅读:
    AcWing 240. 食物链
    AcWing 886. 求组合数 II
    AcWing 734. 能量石
    扩展CRT(扩展中国剩余定理)
    AcWing 12. 背包问题求具体方案
    AcWing 487. 金明的预算方案
    Lucas(卢卡斯)定理
    Neovim下Tutor的常用命令总结
    AcWing 10. 有依赖的背包问题
    AcWing 11. 背包问题求方案数
  • 原文地址:https://www.cnblogs.com/coldchair/p/12913433.html
Copyright © 2020-2023  润新知