zoukankan      html  css  js  c++  java
  • [Codeforces 1251F]Red-White Fence

    Description

    题库链接

    给你 (n) 块白木板,(k) 块红木板,分别有各自的长度 (h_i)。让你用这些木板组成一段围栏,要满足:

    1. 只用一块红木板,且所有白木板的长度均严格小于红木板长度;
    2. 红木板左边的白木板长度严格单调递增;
    3. 红木板右边的白木板长度严格单调递减

    现在给出 (q) 组询问,问周长为 (x_i) 的围栏有多少种。

    (1leq n,h_i,qleq 3cdot 10^5,4leq x_ileq 12cdot 10^5,1leq kleq 5)

    Solution

    如果我们选的红木板长度为 (L),并且这段围栏由 (m) 块板子构成,显然周长为 (2 imes (L+m))

    那么问题就转化为了,求用 (m-1) 块长度 (<L) 的白木板形成两段长度严格单调递增序列的方案数。

    因为木板长度是离散的,我们可以考虑每种长度的木板的放法。

    我们把所有长度 (<L) 的白木板取出。若某种长度的木板只有一块。那么显然,这块木板可以放在红木板的左边或右边(即任意一个序列中)。

    对于某种长度有两块以上的时候,我们可以把他放在左边、右边或者两边都放。并且我们最多只会用 (2) 块这样的木板,所以多余的可以除去。

    假设第一种情况(该长度的木板只有一块)下的木板个数为 (sa)。显然用这 (sa) 块木板构成两段序列总长度为 (i) 的方案数 (a_i={sa choose i} imes 2^i)

    假设第二种情况下的木板个数为 (sb)(除去多余的木板)。用这 (sb) 块木板构成两段序列总长度为 (i) 的的方案数 (b_i={sb choose i})

    记两种情况长度总和为 (i) 的方案数为 (c_i),那么容易发现我们要求的就是

    [ c_{m-1}=sum_{i=0}^{m-1}a_ib_{m-1-i} ]

    这是一个卷积式,那么我们设

    [ egin{aligned} A(x)&=sum_i a_i x^i\ B(x)&=sum_i b_i x^i\ C(x)&=A(x)otimes B(x)\ &=sum_i c_i x^i end{aligned} ]

    那么我们就可以用 ( ext{NTT}) 来求出选该红木板时,对应选不同白木板个数的方案数了。

    因此我们可以枚举每个红木板,做一次 ( ext{NTT}) 累计到答案中,(O(1)) 回答询问。

    总复杂度 (O(k imes nlog n +q))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 12e5+5, yzh = 998244353;
    
    int n, k, q, cnt[N], x, ans[N], fac[N], ifac[N];
    int A[N], B[N], a, b, L, R[N];
    
    int quick_pow(int a, int b) {
        int ans = 1;
        while (b) {
            if (b&1) ans = 1ll*ans*a%yzh;
            b >>= 1, a = 1ll*a*a%yzh;
        }
        return ans;
    }
    int C(int n, int m) {return 1ll*fac[n]*ifac[m]%yzh*ifac[n-m]%yzh; }
    void NTT(int *A, int o) {
        for (int i = 0; i < n; i++) if (i < R[i]) swap(A[i], A[R[i]]);
        for (int i = 1; i < n; i <<= 1) {
            int gn = quick_pow(3, (yzh-1)/(i<<1)), x, y;
            if (o == -1) gn = quick_pow(gn, yzh-2);
            for (int j = 0; j < n; j += (i<<1)) {
                int g = 1;
                for (int k = 0; k < i; k++, g = 1ll*g*gn%yzh) {
                    x = A[j+k], y = 1ll*g*A[j+k+i]%yzh;
                    A[j+k] = (x+y)%yzh;
                    A[j+k+i] = (x-y)%yzh;
                }
            }
        }
    }
    int main() {
        scanf("%d%d", &n, &k);
        fac[0] = ifac[0] = ifac[1] = 1;
        for (int i = 2; i <= n; i++) ifac[i] = -1ll*yzh/i*ifac[yzh%i]%yzh;
        for (int i = 1; i <= n; i++)
            fac[i] = 1ll*i*fac[i-1]%yzh,
            ifac[i] = 1ll*ifac[i-1]*ifac[i]%yzh;
        for (int i = 1; i <= n; i++) scanf("%d", &x), cnt[x]++;
        while (k--) {
            scanf("%d", &x); a = b = 0;
            for (int i = 1; i < x; i++)
                if (cnt[i] >= 2) a += 2;
                else if (cnt[i] == 1) b++;
            memset(A, 0, sizeof(A));
            memset(B, 0, sizeof(B)); 
            for (int i = 0; i <= a; i++) A[i] = C(a, i);
            for (int i = 0; i <= b; i++) B[i] = 1ll*C(b, i)*quick_pow(2, i)%yzh;
            a += b; L = 0;
            for (n = 1; n <= a; n <<= 1) ++L;
            for (int i = 0; i < n; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1));
            NTT(A, 1), NTT(B, 1);
            for (int i = 0; i < n; i++) A[i] = 1ll*A[i]*B[i]%yzh;
            NTT(A, -1);
            int inv = quick_pow(n, yzh-2);
            for (int i = 0; i <= a; i++) A[i] = 1ll*A[i]*inv%yzh;
            for (int i = 0; i <= a; i++) 
                (ans[(x+1+i)<<1] += A[i]) %= yzh;
        }
        scanf("%d", &q);
        while (q--) scanf("%d", &x), printf("%d
    ", (ans[x]+yzh)%yzh);
        return 0;
    }
  • 相关阅读:
    Part 7 Joins in sql server
    Part 9 Union and union all in sql server
    Part 4 using entity framework
    Part 3 ViewData and ViewBag in mvc
    Part 2 How are the URL's mapped to Controller Action Methods?
    Part 1 some difference from asp.net to asp.net mvc4
    Part 18 Indexes in sql server
    c/c++保存日志程序模板
    技术只是工具,你不能用它来代替生活
    网络篇:linux下select、poll、epoll之间的区别总结
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/11741333.html
Copyright © 2011-2022 走看看