题解:P5417 [CTSC2016] 萨菲克斯·阿瑞
神仙计数题。
肯定考虑判定 SA 是否合法,先考虑判定
- 若
rk_{p_i+1}<rk_{p_{i+1}+1} :S_{p_i}\le S_{p_{i+1}} 。 - 反之:
S_{p_i}<S_{p_{i+1}} 。
我们称之为不等式链,易证也是充分的。于是对于一个 SA,可以构建唯一的不等式链
然后可以构造地判断是否存在
为了方便讨论,扔掉
串到 SA 是单射,SA 到
我们不妨枚举
- 对于可以映射到
l 的p ,必然存在且唯一存在一个映射到它的S 满足该多重排列的形式。可以构造地说明,考虑填写不等式链,易发现方案唯一。 - 对于映射到其它不等式链
l_2\ne l ,可以发现l_2 相较于l 只可能是< 号变为\le 号。还是考虑填写l_2 以判定是否会被统计,那么将< 改为\le 并不会影响填写方案唯一,但是改\le 为< 却会使得字符集不够用。 - 称这样的
l_2\subseteq l ,易发现所有映射到l_2 的q ,必然存在且唯一存在一个映射到q 的S 被统计,还是构造,不再赘述。
于是实际上有
回到原题,我们试着贪心构造出可能的不等式链,然后统计对应的 SA。原先的统计方法仍然适用。因为假如一个
可以 dp 解决,回到先前提到的 dp,无非是多了一种转移情况:容斥,允许不填满一段结束。过程中维护容斥系数、多重排列系数即可。转移是平凡的。复杂度
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ADD(a, b) a = (a + b) % mod
const int N = 5e2 + 5, mod = 1e9 + 7;
int n, m, c, f[N][N], g[N][N], h[N][N], jc[N], jcinv[N], ans;
inline int qstp(int a, int k) {int res = 1; for(; k; a = a * a % mod, k >>= 1) if(k & 1) res = res * a % mod; return res;}
signed main(){
jc[0] = jcinv[0] = 1;
for(int i = 1; i < N; ++i) jcinv[i] = qstp(jc[i] = jc[i - 1] * i % mod, mod - 2);
cin >> n >> m;
f[0][0] = jc[n];
for(int i = 1; i <= m; ++i){
scanf("%lld", &c);
if(!c) continue;
swap(f, g), memset(f, 0, sizeof f);
for(int j = 0; j <= n; ++j)
for(int k = 0; k <= j; ++k){
if(j + c <= n) ADD(f[j + c][k + c], g[j][k]);
if(k) h[j][k] = (h[j - 1][k - 1] + g[j - 1][k - 1]) % mod;
if(k >= c + 1) h[j][k] = (h[j][k] - g[j - c - 1][k - c - 1] + mod) % mod;
ADD(f[j][0], h[j][k] * jcinv[k] % mod);
ADD(f[j][k], h[j][k] * (mod - 1) % mod);
}
ADD(ans, f[n][0]);
}
cout << ans;
return 0;
}