Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Problem: B. Subway Pursuit
- // Contest: Codeforces - Codeforces Round #507 (Div. 1, based on Olympiad of Metropolises)
- // URL: https://codeforces.com/contest/1039/problem/B
- // Memory Limit: 512 MB
- // Time Limit: 2000 ms
- //
- // Powered by CP Editor (https://cpeditor.org)
- #include <bits/stdc++.h> //Blitztage
- using namespace std;
- //for loop macros
- #define fo(i,n) for(int i = 0; i < n; i++)
- #define foL(i,n) for(long long i = 0; i < n; i++)
- #define foa(i,k,n) for(int i = k; i < n; i++)
- #define fob(i,k,n) for(int i = k; i >= n; i--)
- #define foaL(i,k,n) for(long long i = k; i < n; i++)
- #define fobL(i,k,n) for(long long i = k; i >= n; i--)
- constexpr int bits(int x) {return x == 0 ? 0 : 31-__builtin_clz(x);}
- //template -> AnandOza && bqi343 Github
- #define pb push_back
- #define eb emplace_back
- #define mp make_pair
- #define F first
- #define S second
- #define resz resize
- #define sz(x) int((x).size())
- #define all(x) (x).begin(), (x).end()
- #define rall(x) (x).rbegin(), (x).rend()
- #define trav(a, x) for (auto &a : x)
- #define L1(u, ...) [&](auto &&u) { return __VA_ARGS__; }
- #define L2(u, v, ...) [&](auto &&u, auto &&v) { return __VA_ARGS__; }
- #define sort_by(x, y) sort(all(x), [&](const auto &l, const auto &r) { return y; })
- #define getunique(v) {sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end());}
- using ld = long double;
- using ll = long long;
- using vi = vector<int>;
- using vvi = vector<vi>;
- using vll = vector<ll>;
- using vvll = vector<vll>;
- using vb = vector<bool>;
- using vvb = vector<vb>;
- using vd = vector<double>;
- using vs = vector<string>;
- using pii = pair<int, int>;
- using pll = pair<ll, ll>;
- using pdd = pair<double, double>;
- using vpii = vector<pii>;
- using vpll = vector<pll>;
- using vpdd = vector<pdd>;
- template <typename T> void ckmin(T &a, const T &b) { a = min(a, b); }
- template <typename T> void ckmax(T &a, const T &b) { a = max(a, b); }
- mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
- namespace __input {
- template <class T1, class T2> void re(pair<T1, T2> &p);
- template <class T> void re(vector<T> &a);
- template <class T, size_t SZ> void re(array<T, SZ> &a);
- template <class T> void re(T &x) { cin >> x; }
- void re(double &x) { string t; re(t); x = stod(t); }
- template <class Arg, class... Args> void re(Arg &first, Args &...rest) { re(first); re(rest...); }
- template <class T1, class T2> void re(pair<T1, T2> &p) { re(p.f, p.s); }
- template <class T> void re(vector<T> &a) { for (int i = 0; i < sz(a); i++) re(a[i]); }
- template <class T, size_t SZ> void re(array<T, SZ> &a) { for (int i = 0; i < SZ; i++) re(a[i]); }
- }
- using namespace __input;
- namespace __output {
- template <typename T> struct is_outputtable { template <typename C> static constexpr decltype(declval<ostream &>() << declval<const C &>(), bool()) test(int) { return true; } template <typename C> static constexpr bool test(...) { return false; } static constexpr bool value = test<T>(int()); };
- template <class T, typename V = decltype(declval<const T &>().begin()), typename S = typename enable_if<!is_outputtable<T>::value, bool>::type> void pr(const T &x);
- template <class T, typename V = decltype(declval<ostream &>() << declval<const T &>())> void pr(const T &x) { cout << x; }
- template <class T1, class T2> void pr(const pair<T1, T2> &x);
- template <class Arg, class... Args> void pr(const Arg &first, const Args &...rest) { pr(first); pr(rest...); }
- template <class T, bool pretty = true> void prContain(const T &x) { if (pretty) pr("{"); bool fst = 1; for (const auto &a : x) pr(!fst ? pretty ? ", " : " " : "", a), fst = 0; if (pretty) pr("}"); }
- template <class T> void pc(const T &x) { prContain<T, false>(x); pr("\n"); }
- template <class T1, class T2> void pr(const pair<T1, T2> &x) { pr("{", x.f, ", ", x.s, "}"); }
- template <class T, typename V, typename S> void pr(const T &x) { prContain(x); }
- void ps() { pr("\n"); }
- template <class Arg> void ps(const Arg &first) { pr(first); ps(); }
- template <class Arg, class... Args> void ps(const Arg &first, const Args &...rest) { pr(first, " "); ps(rest...); }
- }
- using namespace __output;
- #define __pn(x) pr(#x, " = ")
- #ifdef ANAND_LOCAL
- #define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush
- #else
- #define pd(...)
- #endif
- namespace __algorithm {
- template <typename T> void dedup(vector<T> &v) { sort(all(v)); v.erase(unique(all(v)), v.end()); }
- template <typename T> typename vector<T>::const_iterator find(const vector<T> &v, const T &x) { auto it = lower_bound(all(v), x); return it != v.end() && *it == x ? it : v.end(); }
- template <typename T> size_t index(const vector<T> &v, const T &x) { auto it = find(v, x); assert(it != v.end() && *it == x); return it - v.begin(); }
- template <typename I> struct _reversed_struct { I &v_; explicit _reversed_struct(I &v) : v_{v} {} typename I::reverse_iterator begin() const { return v_.rbegin(); } typename I::reverse_iterator end() const { return v_.rend(); } };
- template <typename I> _reversed_struct<I> reversed(I &v) { return _reversed_struct<I>(v); }
- }
- using namespace __algorithm;
- namespace __io {
- void setIO() { ios_base::sync_with_stdio(0); cin.tie(0); cout << setprecision(15); }
- }
- using namespace __io;
- template<typename T_vector>
- void outvec(const T_vector &v, bool add_one = false, int start = -1, int end = -1) {
- if (start < 0) start = 0;
- if (end < 0) end = int(v.size());
- for (int i = start; i < end; i++)
- cout << v[i] + (add_one ? 1 : 0) << (i < end - 1 ? ' ' : '\n');
- }
- //#define int long long
- #define noo {ps("NO");return;}
- #define yess {ps("YES");return;}
- #define GOOGLE 0
- const ld pi = 3.14159265358979323846;
- const ll N = 7e5;
- //Global declarations
- //ll n, m, k, l, r, x, y, z;
- //string s, t;
- //const ll mod = 1000000007;
- #define Multitests 1
- //auto seed = chrono::high_resolution_clock::now().time_since_epoch().count();
- //std::mt19937 mt(seed);
- //int myrand(int mod) {
- //return mt()%mod;
- //}
- // Globally declared
- vector<vector<int>> seg;
- // This function mergers two sorted arrays
- vector<int> merge(vector<int> &a1, vector<int> &a2)
- {
- int n = a1.size(), m = a2.size();
- int i = 0, j = 0;
- vector<int> res;
- while (i < n and j < m)
- {
- if (a1[i] < a2[j])
- {
- res.push_back(a1[i]);
- i += 1;
- }
- else
- {
- res.push_back(a2[j]);
- j += 1;
- }
- }
- while (i < n)
- {
- res.push_back(a1[i++]);
- }
- while (j < m)
- {
- res.push_back(a2[j++]);
- }
- return res;
- }
- // This function builds the segment tree
- void buildST(int idx, int low, int high, vector<int> &input)
- {
- // Base case: when there is a single elment in the range [LOW, HIGH]
- if (low == high)
- {
- seg[idx].push_back({input[low]});
- return;
- }
- int mid = (low + high) / 2;
- // Recursive calls to build the left and right subtrees
- buildST(2 * idx + 1, low, mid, input);
- buildST(2 * idx + 2, mid + 1, high, input);
- /*
- The current node's value is calculated by merging
- the values of the left and the right nodes.
- */
- seg[idx] = merge(seg[2 * idx + 1], seg[2 * idx + 2]);
- }
- int queryHelper(int idx, int l, int r, int low, int high,int k)
- {
- // When a node is completely inside
- if (low >= l and high <= r)
- {
- return int(upper_bound(all(seg[idx]),k) - seg[idx].begin());
- }
- // When a node is completely outside
- if (r < low or l > high)
- {
- return 0;
- }
- int mid = (low + high) / 2;
- /*
- Fetch sorted subarray from the left and the right subtrees
- and merge them to get a sorted array in the range [l, r]
- */
- int left = queryHelper(2 * idx + 1, l, r, low, mid,k);
- int right = queryHelper(2 * idx + 2, l, r, mid + 1, high,k);
- return left + right;
- }
- int query(int l, int r, int k, int n)
- {
- return queryHelper(0, l, r, 0, n - 1,k);
- }
- using v_t = int;
- using vv_t = int64_t;
- template<v_t MOD> struct modnum {
- static_assert(std::numeric_limits<v_t>::max() / 2 >= MOD, "Addition overflows v_t");
- static_assert(std::numeric_limits<vv_t>::max() / MOD >= MOD, "Multiplication overflows vv_t");
- v_t v;
- modnum() : v(0) {}
- modnum(vv_t _v) : v(v_t(_v % MOD)) { if (v < 0) v += MOD; }
- explicit operator v_t() const { return v; }
- friend std::istream& operator >> (std::istream& i, modnum& n) { vv_t w; i >> w; n = modnum(w); return i; }
- friend std::ostream& operator << (std::ostream& o, const modnum& n) { return o << n.v; }
- friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
- friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }
- friend bool operator < (const modnum& a, const modnum& b) { return a.v < b.v; }
- static unsigned fast_mod(uint64_t x, unsigned m = MOD) {
- #if !defined(_WIN32) || defined(_WIN64)
- return unsigned(x % m);
- #endif
- // x must be less than 2^32 * m so that x / m fits in a 32-bit integer.
- unsigned x_high = unsigned(x >> 32), x_low = unsigned(x), quot, rem;
- asm("divl %4\n"
- : "=a" (quot), "=d" (rem)
- : "d" (x_high), "a" (x_low), "r" (m));
- return rem;
- }
- modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
- modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
- modnum& operator *= (const modnum& o) { v = fast_mod(vv_t(v) * o.v); return *this; }
- modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
- friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
- friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
- friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }
- modnum& operator ++ () { return *this += 1; }
- modnum& operator -- () { return *this -= 1; }
- modnum operator ++ (int) { auto old = *this; operator++(); return old; }
- modnum operator -- (int) { auto old = *this; operator--(); return old; }
- modnum pow(vv_t e) const {
- if (e < 0) return 1 / this->pow(-e);
- if (e == 0) return 1;
- if (e & 1) return *this * this->pow(e-1);
- return (*this * *this).pow(e/2);
- }
- modnum inv() const {
- v_t g = MOD, x = 0, y = 1;
- for (v_t r = v; r != 0; ) {
- v_t q = g / r;
- g %= r; std::swap(g, r);
- x -= q * y; std::swap(x, y);
- }
- assert(g == 1);
- assert(y == MOD || y == -MOD);
- return x < 0 ? x + MOD : x;
- }
- modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
- friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }
- static constexpr v_t modulus() { return MOD; }
- static constexpr v_t totient() {
- v_t tot = MOD, tmp = MOD;
- for (v_t p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
- tot = tot / p * (p - 1);
- while (tmp % p == 0) tmp /= p;
- }
- if (tmp > 1) tot = tot / tmp * (tmp - 1);
- return tot;
- }
- static v_t primitive_root() {
- if (MOD == 1) return 0;
- if (MOD == 2) return 1;
- v_t tot = totient(), tmp = tot;
- std::vector<int> tot_pr;
- for (v_t p = 2; p * p <= tmp; p++) if (tot % p == 0) {
- tot_pr.push_back(p);
- while (tmp % p == 0) tmp /= p;
- }
- if (tmp > 1) tot_pr.push_back(tmp);
- for (v_t r = 2; r < MOD; r++) if (std::gcd(r, MOD) == 1) {
- bool root = true;
- for (v_t p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
- if (root) return r;
- }
- assert(false);
- }
- static modnum generator() { static modnum g = primitive_root(); return g; }
- static v_t discrete_log(modnum v) {
- static const v_t M = ceil(std::sqrt(MOD));
- static std::unordered_map<v_t, v_t> table;
- if (table.empty()) {
- modnum e = 1;
- for (v_t i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
- }
- static modnum f = generator().pow(totient() - M);
- for (v_t i = 0; i < M; i++) {
- if (table.count(v.v)) return table[v.v] + i * M;
- v *= f;
- }
- assert(false);
- }
- static modnum unity_root(int deg) {
- assert(totient() % deg == 0);
- return generator().pow(totient() / deg);
- }
- static modnum unity_root(int deg, int pow) {
- static std::vector<modnum> table{ 0, 1 };
- while (int(table.size()) <= deg) {
- modnum w = unity_root(int(table.size()));
- for (int s = int(table.size()), i = s / 2; i < s; i++) {
- table.push_back(table[i]);
- table.push_back(table[i] * w);
- }
- }
- return table[deg + (pow < 0 ? deg + pow : pow)];
- }
- static modnum factorial(int n) {
- static std::vector<modnum> fact = {1};
- assert(n >= 0);
- if (int(fact.size()) <= n) {
- int had = fact.size();
- fact.resize(n + 1);
- for (int i = had; i <= n; i++) fact[i] = fact[i-1] * i;
- }
- return fact[n];
- }
- static modnum inverse_factorial(int n) {
- static std::vector<modnum> finv = {1};
- assert(n >= 0);
- if (int(finv.size()) <= n) {
- int had = finv.size();
- finv.resize(n + 1), finv[n] = factorial(n).inv();
- for (int i = n - 1; i >= had; i--) finv[i] = finv[i+1] * (i+1);
- }
- return finv[n];
- }
- static modnum small_inv(int n) {
- assert(n > 0); return factorial(n - 1) * inverse_factorial(n);
- }
- static modnum ncr(int n, int r) {
- if (r < 0 || n < r) return 0;
- return factorial(n) * inverse_factorial(r) * inverse_factorial(n - r);
- }
- };
- using mn = modnum<int(1e9 + 7)>;
- void solve(){
- ll n;
- cin >> n;
- vector<int> arr(n);
- fo(i,n) cin >> arr[i];
- // Setting up globals
- seg.clear();
- seg.resize(4 * n);
- // Building the segment tree
- buildST(0, 0, n - 1, arr);
- ll q;
- cin >> q;
- fo(i,q){
- int l,r,x;
- cin >> l >> r >> x;
- l--; r--;
- int y = query(l ,r, x, n);
- mn ans = mn::factorial(r - l + 1);
- ans /= mn::factorial(y);
- ans /= mn::factorial(r - l + 1 - y);
- //ps(y);
- ps(ans);
- }
- }
- int32_t main(){
- //sieve();
- setIO();
- #if Multitests
- int t; cin >> t;
- for(int i = 0; i < t; i++){
- #if GOOGLE
- cout<<"Case #"<<i + 1<<": ";
- #endif
- solve();
- }
- #else
- solve();
- #endif
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement