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))