【2020.11.16提高组模拟】序列翻转 题解
【2020.11.16提高组模拟】序列翻转 题解
题目简述
求一个\(01\)串经过k次以下的操作有多少种方案数。其中,操作\(A\)和\(B\)按照不同顺序进行(\(AB\)、\(BA\))视其为不用的操作,即使\(AB\)互相不干扰。
定义合法序列:形如\(10101...10101\)的串,\(i\)维的合法串长度为\(2i+1\)。
操作方法:对一个合法序列中的所有\(01\)取反。
数据范围
\(type\) | \(n\le\) | k | |
---|---|---|---|
\(1\) | \(1\) | \(6\) | \(\le n\) |
\(2\) | \(1\) | \(10\) | \(\le n\) |
\(3\) | \(1\) | \(17\) | \(\le n\) |
\(4\) | \(1\) | \(20\) | \(\le n\) |
\(5\) | \(1\) | \(23\) | \(\le n\) |
\(6\) | \(1\) | \(23\) | \(\le n\) |
\(7\) | \(2\) | \(40\) | \(\le n+1\) |
\(8\) | \(2\) | \(40\) | \(\le n+1\) |
\(9\) | \(2\) | \(60\) | \(\le n+1\) |
\(10\) | \(2\) | \(60\) | \(\le n+1\) |
\(11\) | \(2\) | \(60\) | \(\le n+1\) |
\(12\) | \(2\) | \(80\) | \(\le n+1\) |
\(13\) | \(2\) | \(100\) | \(\le n+1\) |
\(14\) | \(2\) | \(110\) | \(\le n+1\) |
\(15\) | \(2\) | \(110\) | \(\le n+1\) |
\(16\) | \(2\) | \(120\) | \(\le n+1\) |
\(17\) | \(2\) | \(120\) | \(\le n+1\) |
\(18\) | \(2\) | \(500\) | \(=n+1\) |
\(19\) | \(2\) | \(1000\) | \(=n+1\) |
\(20\) | \(2\) | \(5000\) | \(=n+1\) |
\(21\) | \(2\) | \(10^5\) | \(=n+1\) |
\(22\) | \(2\) | \(10^7\) | \(=n+1\) |
\(23\) | \(2\) | \(10^9\) | \(=n+1\) |
\(24\) | \(2\) | \(10^{18}\) | \(=n+1\) |
\(25\) | \(2\) | \(10^{18}\) | \(=n+1\) |
题意分析
首先看到这道题目的数据范围十分有趣,可以大做文章。
Subtask1
\(type=1,n\le23\)
显然暴力将\(n^2*2^n\)的爆搜进行状压写成\(dp\)即可通过。
Subtask2
\(type=2,n,k\le120\)
\(n\)比较小,那么我们可以暴力区间\(dp\)。
我们对一串\(10101...\)枚举一段区间,反转。
可以观察之后,串变成了三个不互相干扰的独立串。
所以可以分开做。
但是这样是\(n^3\cdot k^3\)的。
考虑优化。
只要枚举被反转的区间的左端点在哪里即可。
设g(x)表示左端点\(x\)被砍了一刀,但是右端点不知道在哪的方案数。(右区间要枚举)
最后合并即可。
Subtask3
\(type=2,n\le 10^{18},k=n+1\)
打表可以发现答案就是\(1*3*5*7*...*(2k-1)\)
即
证明也很简单玄学。每一次取出一段合法序列操作时,都会将这一个序列减少一个1。进行\(n+1\)次操作后,整个序列一定是全0的了。接着用组合数拆开、乘法原理乘起来就好。
但是直接阶乘无法通不过\(n=10^{9}\)。
其实当\(mod\le 2i+1\)时,这个连乘的式子中会有一个998244353。
又因为998244353是一个质数,所以\(1\times3\times...\times998244353\times998244355\times...=0\)!(这个!不是阶乘哈)
中间的数据还是会T,分块打表即可。