题解:AT_agc036_f [AGC036F] Square Constraints
Priestess_SLG · · 题解
题目中给的东西其实就是要求排列对应的坐标点落在大圆和小圆之间求排列的数量。记
考虑对内圆
考虑算
考虑进一步优化时间复杂度。容易想到 dp,套路的把所有的
然后考虑如果当前遇到了一个
如果选
如果不选
扫描完之后
:::success[Code]
namespace lowspeed_song {
inline void init() {
}
int F[N], nF[N];
inline void sol([[maybe_unused]]int __testcase_id) {
int n, mod; cin >> n >> mod;
vector<pair<int, int>> a;
for (int i = 0; i < n; ++i) {
int l = 0, r = 2 * n - 1;
while ((l + 1) * (l + 1) + i * i < n * n) ++l;
while (r * r + i * i > 4 * n * n) --r;
a.emplace_back(l, r);
}
for (int i = n; i < 2 * n; ++i) {
int r = 2 * n - 1;
while (r * r + i * i > 4 * n * n) --r;
a.emplace_back(r, 0);
}
sort(a.begin(), a.end());
function<int(int)> calc = [&](int k) {
fill(F, F + n + 1, 0), F[0] = 1;
int c1 = 0, c2 = 0;
for (auto &[l, r] : a) {
fill(nF, nF + n + 1, 0);
if (!r) {
for (int j = 0; j <= c2; ++j) nF[j] = F[j] * (l - c1 - j + 1) % mod;
++c1;
} else {
for (int j = 0; j <= c2; ++j) nF[j + 1] = (nF[j + 1] + F[j] * (l - c1 - j + 1) % mod) % mod, nF[j] = (nF[j] + F[j] * (r - (n + c2 - j + k) + 1) % mod) % mod;
++c2;
} copy(nF, nF + n + 1, F);
} return F[k];
};
int res = 0;
for (int k = 0; k <= n; ++k)
if (k & 1) res = (res - calc(k) + mod) % mod;
else res = (res + calc(k)) % mod;
cout << res << '\n';
}
} // namespace lowspeed_song
:::