Square Constraints
Square Constraints
题意
- 给定
n ,求满足以下条件的0 \sim 2n-1 的排列p_{0\dots2n-1} 的个数。- 对于
i \in [0,2n-1] ,满足n^2 \le i^2 + p_i^2 \le (2n)^2 。
- 对于
-
题解
本质上,这依然是一个
在没有下界限制的情况下,我们有个经典的做法是,将
在有下界时,我们可以考虑容斥,设
回到本题,题意的约束条件比较奇怪,考虑将它变得直观一点就是:
- 以原点为圆心在第一象限画两个半径分别为
n,2n 的1/4 圆,对于i \in [0,2n-1] ,(i,p_i) 必须在这两个1/4 圆之间(含圆上)。
于是我们有
考虑枚举若干个
然而显然我们不能枚举每个
注意到对
考虑:
- 对于
i \in[0,n-1] ,以l_i - 1 为第一关键字,r_i 为第二关键字。 - 对于
i \in [n, 2n-1] ,以r_i 为第一关键字,l_i-1 为第二关键字。
排序,设排序后的序列为
考虑 DP,设
设
-
若
q_i \in [0,n-1] ,且只要求p_{q_i} \le r_{q_i} ,其贡献为:- 所有 $i \in [n,2n-1]$ 的 $r_i$($n$ 个) - $q_{1\dots i-1}$ 中 $\in[0,n-1]$ 的 $q$($t$ 个) - $q_{i+1\dots 2n-1}$ 中 $\in [0,n-1]$ 且要求 $<l$ 的 $q$($k-j$ 个) 转移:$f_{i,j}\leftarrow f_{i-1,j} \cdot (r_{q_i} + 1 - (n + t + k - j))$。 -
若
q_i \in [0,n-1] ,且要求p_{q_i} < l_{q_i} ,其贡献为:- $q_{1\dots i-1}$ 中 $\in [n,2n-1]$ 的 $q$($i-1-t$ 个) - $q_{1\dots i-1}$ 中 $\in[0,n-1]$ 且要求 $<l$ 的 $q$($j-1$ 个) 转移:$f_{i,j} \leftarrow f_{i-1,j-1} \cdot (l_{q_i} - (i-1-t+(j-1)))$。 -
若
q_{n,2n-1} ,其贡献为:- $q_{1\dots i-1}$ 中 $\in [n,2n-1]$ 的 $q$($i-1-t$ 个) - $q_{1\dots i-1}$ 中 $\in[0,n-1]$ 且要求 $<l$ 的 $q$($j$ 个) 转移:$f_{i,j} \leftarrow f_{i-1,j} \cdot (r_{q_i} + 1 - (i-1-t+j))$。
时间复杂度
代码
const int N = 507;
int n, l[N], r[N], q[N];
modint f[N][N], ans;
inline modint calc(int k) {
f[0][0] = 1;
for (int i = 1, t = 0; i <= n << 1; t += q[i] < n, i++)
for (int j = 0; j <= min(min(i, k), t + (q[i] < n)); j++)
if (q[i] < n) f[i][j] = f[i-1][j] * (r[q[i]] + 1 - (n + t + k - j)) + (j ? f[i-1][j-1] * (l[q[i]] - (i - 1 - t + (j - 1))) : 0);
else f[i][j] = f[i-1][j] * (r[q[i]] + 1 - (i - 1 - t + j));
return f[n<<1][k];
}
int main() {
rd(n, P);
for (int i = 0; i < n << 1; i++)
l[i] = max(0, (int)ceil(sqrt(n * n - i * i))),
r[i] = min(2 * n - 1, (int)floor(sqrt(4 * n * n - i * i))),
q[i+1] = i;
sort(q + 1, q + (n << 1 | 1), [&](int i, int j) {
pi x = i < n ? mp(l[i] - 1, r[i]) : mp(r[i], l[i] - 1);
pi y = j < n ? mp(l[j] - 1, r[j]) : mp(r[j], l[j] - 1);
return x < y;
});
for (int i = 0; i <= n; i++)
if (i & 1) ans -= calc(i);
else ans += calc(i);
print(ans);
return 0;
}