Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- typedef long double ld;
- typedef long long ll;
- #define pb push_back
- #define iter(X) X.begin(), X.end()
- const ll maxN = 5e3 + 1;
- const ll MOD = (ll)1e9 + 7;
- const ld PI = acos(-1);
- // Corrected FFT implementation
- namespace FFT {
- struct Complex {
- ld x, y;
- Complex(ld x = 0, ld y = 0) : x(x), y(y) {}
- Complex operator+(const Complex &c) const { return Complex(x + c.x, y + c.y); }
- Complex operator-(const Complex &c) const { return Complex(x - c.x, y - c.y); }
- Complex operator*(const Complex &c) const { return Complex(x * c.x - y * c.y, x * c.y + y * c.x); }
- };
- void fft(vector<Complex> &a, bool invert) {
- int n = a.size();
- for (int i = 1, j = 0; i < n; i++) {
- int bit = n >> 1;
- for (; j >= bit; bit >>= 1) j -= bit;
- j += bit;
- if (i < j) swap(a[i], a[j]);
- }
- for (int len = 2; len <= n; len <<= 1) {
- ld ang = 2 * PI / len * (invert ? -1 : 1);
- Complex wlen(cos(ang), sin(ang));
- for (int i = 0; i < n; i += len) {
- Complex w(1, 0);
- for (int j = 0; j < len / 2; j++) {
- Complex u = a[i + j], v = a[i + j + len / 2] * w;
- a[i + j] = u + v;
- a[i + j + len / 2] = u - v;
- w = w * wlen;
- }
- }
- }
- if (invert) {
- for (Complex &x : a) x.x /= n, x.y /= n;
- }
- }
- vector<ll> multiply(const vector<ll> &a, const vector<ll> &b) {
- // Trim leading zeros first
- int asize = a.size(), bsize = b.size();
- while (asize > 0 && a[asize-1] == 0) asize--;
- while (bsize > 0 && b[bsize-1] == 0) bsize--;
- int n = 1;
- while (n < asize + bsize) n <<= 1;
- vector<Complex> fa(n), fb(n);
- for (int i = 0; i < asize; i++) fa[i] = Complex(a[i], 0);
- for (int i = 0; i < bsize; i++) fb[i] = Complex(b[i], 0);
- fft(fa, false);
- fft(fb, false);
- for (int i = 0; i < n; i++) fa[i] = fa[i] * fb[i];
- fft(fa, true);
- vector<ll> res(n);
- for (int i = 0; i < n; i++) {
- res[i] = (ll)(fa[i].x + 0.5) % MOD;
- }
- // Trim trailing zeros
- while (!res.empty() && res.back() == 0) res.pop_back();
- return res;
- }
- }
- // Your existing code remains unchanged
- vector<ll> fact(maxN + 1, 1);
- vector<ll> invFact(maxN + 1, 0);
- ll binpow(ll a, ll b) {
- a %= MOD;
- ll res = 1;
- while (b > 0) {
- if (b & 1) res = res * a % MOD;
- a = a * a % MOD;
- b >>= 1;
- }
- return res % MOD;
- }
- void prec() {
- for (ll i = 2; i <= maxN; i++) {
- fact[i] = (fact[i-1] * i) % MOD;
- }
- invFact[maxN] = binpow(fact[maxN], MOD-2);
- for (ll i = maxN-1; i >= 0; --i) {
- invFact[i] = (invFact[i+1] * (i+1)) % MOD;
- }
- }
- ll C(ll n, ll r) {
- if (r < 0 || n < 0 || r > n) return 0;
- return (fact[n] * invFact[r] % MOD) * invFact[n-r] % MOD;
- }
- void solve() {
- int n;
- cin >> n;
- vector<ll> v(n);
- for (auto &a : v) cin >> a;
- vector<ll> pfx(n, 0);
- pfx[0] = (v[0] == -1);
- for (int i = 1; i < n; ++i) {
- pfx[i] = pfx[i-1] + (v[i] == -1);
- }
- ll res = 0;
- for (int k = 0; k <= n-1; ++k) {
- bool t =1;
- int MinJ = 0, MaxI = n-1;
- for (int i = 0; i < n; ++i) {
- if (v[i] != -1 && v[i] <= k) {
- t = 0;
- MinJ = max(MinJ, i);
- MaxI = min(MaxI, i);
- }
- }
- ll val = 0;
- for (int i = 0; i < n; ++i) {
- if (v[i] != -1 && v[i] <= k) val++;
- }
- vector<ll> L(n+1, 0), R(n+1, 0);
- int tmpL = 0, tmpR = 0;
- for (int i = MaxI; i >= 0; --i) {
- if (v[i] == -1) tmpL++;
- L[tmpL]++;
- }
- for (int i = MinJ; i < n; ++i) {
- if (v[i] == -1) tmpR++;
- R[tmpR]++;
- }
- // FFT-based convolution
- vector<ll> conv = FFT::multiply(L, R);
- ll need = k+1 - val;
- /*
- if (t){
- //It seems i need to fix this part.
- continue;
- }
- */
- for (ll i = 0; i <= tmpL + tmpR; ++i){
- ll Minuses = pfx[MinJ] - (MaxI == 0 ? 0 : pfx[MaxI-1]) + i;
- if (Minuses < 0 || Minuses > pfx[n-1]) continue;
- ll term = (conv[i] * C(Minuses, need)) % MOD;
- term = (term * fact[need]) % MOD;
- term = (term * fact[pfx[n-1] - need]) % MOD;
- res = (res + term) % MOD;
- }
- }
- cout << res << endl;
- }
- int main() {
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
- prec();
- int t;
- cin >> t;
- while (t--) solve();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment