• jiangly CSP2020模拟赛 部分题解


    T3

    思路:按位分治

    大概就是从高到低考虑二进制的每一位

    (solve(S,i))表示当前我们考虑在(S)这个集合中选,当前只需要考虑只取出第(i)位及以下的限制(x),满足题意的方案数

    那么对限制的第(i)位,我们把(S)中第(i)位是(1)和是(0)的分成两个集合(A)(B)

    接下来讨论

    如果限制的这一位是(1)的的话,我们显然只能在(A)(B)中各至多选择一个,否则异或出来必然存在这一位是(0)

    那么此时我们就满足了(x)(i)位的限制

    于是这一个我们可以考虑对(A)建一棵trie,对(B)中的每一个数在trie数上统计满足(x)的后(i-1)位的方案数,这一部分总复杂度是(O(nlog a_i))

    如果限制的这一位是(0)的的话,我们从两个集合中各拉出来一个数异或起来显然是(>=x)的,所以只需要考虑A和B内部的选择,我们发现这变成了两个子问题(solve(A,i-1)) (solve(B,i-1))的答案的积

    我们发现总共分治(log a_i)层,每层总个数不超过(n),所以这部分总复杂度也是(O(nlog a_i))

    总复杂度(O(nlog a_i))


    T4

    思路:容斥

    我们考虑把每个(k)的答案分开来计算

    首先我们发现,对于操作次数为(k)的答案是所有最长上升子串长度至少是(n-k)的排列的个数

    这一点不难证明,此处略去

    我们考虑用总排列数减去所有不含长度至少是(n-k)的上升子串的方案数

    这一部分我们可以考虑容斥,用总方案数减去钦定了一个长度是(n-k)的上升子串的方案,再加上两个(n-k)的上升子串的方案数....

    但是我们注意到多个重叠的上升子串是需要合并的

    于是我们就可以把长度为(x)的上升子串的所有能够构成他的方案的容斥系数求出来,这里我们认为不属于任意一个上升子串的单个数,其长度是(1)

    然后这里可以dp,大概就是

    (f[1]=1 f[n-k]=-1)

    (f[i]=-sum_{j=1}^{n-k-1}f[i-j])

    得到这个以后就可以计算了

    我们设(g[i])表示总长度是i的所有排列方案的容斥系数总和

    那么(g[i]=sum_{j=1}^{i}g[i-j]f[j])

    但是我们还要给每一个上升子串分配他是哪些数怎么搞

    我们发现分配方案恰为(frac{n!}{prod a_i!})其中(a_i)是我们钦定的每一个上升子串的长度

    (n!)可以提出来,(a_i!)这个东西是可以揉到容斥系数里的,即对于dp出来的(f_i)都乘上(frac{1}{i!})

    单次dp复杂度是(O(n^2)),总复杂度是(O(n^3))

    过不了怎么办?

    我们把dp出来的(f[i])打出来,发现一个惊人的事情!

    对于(i=(n-k)*t)(f[i])(-1)

    对于(i=(n-k)*t+1)(f[i])(1)

    其他的都是(0)

    其实这一点非常好证,此处略去

    于是我们的转移只有(n/(n-k))

    单次dp复杂度降至(O(frac{n^2}{n-k})),总复杂度降至(O(n^2ln n))

  • 相关阅读:
    求24点
    关于参数和返回值的常量性
    点到平面的距离公式
    大端序与小端序
    Quake3中的绝对值函数
    整数超出范围时如何表示?
    关于数组的几道面试题
    在移位数组中查找数
    时间复杂度O(n),空间复杂度O(1)的排序
    C++之对象切割
  • 原文地址:https://www.cnblogs.com/deaf/p/13804783.html
Copyright © 2020-2023  润新知