zoukankan      html  css  js  c++  java
  • 【集训队作业2018】count

    CSP后第一发Blog。

    这道题没有一下子过掉,开始还推出了错的结论。在错误的生成函数里绕了好久……


    很显然的转笛卡尔树,一个笛卡尔树对应一种序列。只要考虑一个笛卡尔树是否合法。

    贪心地填数发现,从根到每一个叶子最多只能有 (m - 1) 个向左。

    于是直接上生成函数。设 (f_m(x)) 为至多有 (m) 个向左的方案数,显然 (f_m = x f_{m-1} f_m + 1)

    解出 (f_m = frac{1}{1-x f_{m-1}}),设 (f_m = frac{A_m}{B_m}),可以列出线性递推。因为 (B) 每次最多乘 (x),次数不超过 (n),线性递推就可以使用点值来做到 (Oleft(n log n ight))

    也可以转括号序列,多叉转二叉后变成栈高度不能超过 (m)

    左括号看做向上,右括号看做向右,那么就是有上下边界限制的网格图路径问题。

    该问题比较特殊,只有 (fleft(x ight) = x)(fleft(x ight) = x + m),可以通过设 (fleft(x ight) = x) 上方格子的 DP 值找规律归纳证明出 DP值的关系。

    也可以直接容斥经过这两条边的情况。根据卡特兰数推导过程,我们可以把起点到 (fleft(x ight) = x - 1)(fleft(x ight) = x + m + 1)轴对称,那么 新的点到终点的路径 对应着 原图中原点到终点经过这条边的路径。

    多次翻折也类似。我们考虑经过两条线的情况,一定是交替的出现,所以容斥一下经过几次线就能算出答案。

    总之做法很多。样例好评,注意坐标会爆int。

    #include <bits/stdc++.h>
    
    const int mod = 998244353;
    const int MAXN = 200010;
    typedef long long LL;
    void reduce(int & x) { x += x >> 31 & mod; }
    int mul(int a, int b) { return (LL) a * b % mod; }
    int fac[MAXN], inv[MAXN];
    int C(int a, LL b) {
    	return a < b || b < 0 ? 0 : (LL) fac[a] * inv[b] % mod * inv[a - b] % mod;
    }
    typedef std::pair<LL, LL> PII;
    PII flip(PII x, LL b) { return PII(x.second - b, x.first + b); }
    int n, m;
    int main() {
    	std::ios_base::sync_with_stdio(false), std::cin.tie(0);
    	std::cin >> n >> m;
    	if (m > n) { std::cout << 0 << '
    '; return 0; }
    	fac[0] = fac[1] = inv[0] = inv[1] = 1;
    	for (int i = 2; i != MAXN; ++i) {
    		fac[i] = mul(fac[i - 1], i);
    		inv[i] = mul(inv[mod % i], mod - mod / i);
    	}
    	for (int i = 2; i != MAXN; ++i) inv[i] = mul(inv[i - 1], inv[i]);
    	PII a(0, 0), b(0, 0);
    	int ans = C(n * 2, n);
    	for (int i = 1, coef = 1; i <= n; ++i, coef = mod - coef) {
    		if (i & 1) a = flip(a, -1), b = flip(b, m + 1);
    		else a = flip(a, m + 1), b = flip(b, -1);
    		reduce(ans -= mul(coef, C(n * 2, n - a.first)));
    		reduce(ans -= mul(coef, C(n * 2, n - b.first)));
    	}
    	std::cout << ans << '
    ';
    	return 0;
    }
    

    听说还有多边形限制网格图路径的题…… /px

  • 相关阅读:
    C语言 · 字符串输入输出函数
    C语言 · 判定字符位置
    剑指offer二之替换空格
    剑指offer一之二维数组中的查找
    算法复杂度:时间复杂度与空间复杂度
    二分查找法
    信息熵
    K-means算法的原理、优缺点及改进(转)
    office2013安装与卸载
    Deep Learning (中文版&英文版)
  • 原文地址:https://www.cnblogs.com/daklqw/p/11887945.html
Copyright © 2011-2022 走看看