Submission #1272423

#TimeUsernameProblemLanguageResultExecution timeMemory
1272423ArtRelativnost (COCI15_relativnost)C++20
56 / 140
779 ms49812 KiB
// - Art - #include <bits/stdc++.h> #define el cout << '\n' #define FOR(i, a, b) for (int i = (a), _b = (b); i <= _b; ++i) #define REV(i, b, a) for (int i = (b), _a = (a); i >= _a; --i) #define REP(i, c) for (int i = 0, _c = (c); i < _c; ++i) const int N = 1e5 + 7; const int MOD = 1e4 + 7; const int BLOCKSIZE = 578; const int NUMBLOCK = N / BLOCKSIZE + 7; using namespace std; int a[N], b[N]; namespace naive { int dp[N][22]; void solve(int n, int k) { int q; cin >> q; while (q--) { int id, na, nb; cin >> id >> na >> nb; na %= MOD; nb %= MOD; a[id] = na; b[id] = nb; dp[0][0] = 1; FOR (i, 1, n) REP (j, k) { dp[i][j] = dp[i - 1][j] * b[i] % MOD; if (j > 0) { dp[i][j] = (dp[i][j] + dp[i - 1][j - 1] * a[i]) % MOD; } } int tot = 1; FOR (i, 1, n) { tot = (a[i] + b[i]) * tot % MOD; } REP (i, k) { tot = (tot - dp[n][i] + MOD) % MOD; } cout << tot, el; } } } int inverse(int a) { int b = MOD - 2, res = 1; while (b) { if (b & 1) { res = res * a % MOD; } a = a * a % MOD; b >>= 1; } return res; } namespace blocksqrt { int block[N]; int dp[NUMBLOCK][22]; int pre[NUMBLOCK][22]; void solve(int n, int k) { int tot = 1; REP (i, n) { block[i] = i / BLOCKSIZE; a[i] = a[i + 1]; b[i] = b[i + 1]; tot = (a[i] + b[i]) * tot % MOD; } FOR (x, 0, block[n - 1]) { int l = x * BLOCKSIZE; int r = min(n, l + BLOCKSIZE) - 1; dp[x][0] = b[l]; dp[x][1] = a[l]; FOR (i, l + 1, r) REV (j, k - 1, 0) { dp[x][j] = (dp[x][j] * b[i]) % MOD; if (j > 0) { dp[x][j] = (dp[x][j] + dp[x][j - 1] * a[i]) % MOD; } } if (x > 0) { REP (j, k) REP (o, j + 1) { pre[x][j] = (pre[x][j] + pre[x - 1][o] * dp[x][j - o]) % MOD; } } else { REP (j, k) { pre[x][j] = dp[x][j]; } } } int q; cin >> q; while (q--) { int id, na, nb; cin >> id >> na >> nb; na %= MOD; nb %= MOD; --id; tot = tot * inverse(a[id] + b[id]) % MOD; tot = tot * (na + nb) % MOD; a[id] = na; b[id] = nb; int x = block[id]; int l = x * BLOCKSIZE; int r = min(n, l + BLOCKSIZE) - 1; memset(dp[x], 0, sizeof dp[x]); dp[x][0] = b[l]; dp[x][1] = a[l]; FOR (i, l + 1, r) { REV (j, k - 1, 0) { dp[x][j] = dp[x][j] * b[i] % MOD; if (j > 0) { dp[x][j] = (dp[x][j] + dp[x][j - 1] * a[i]) % MOD; } } } int res = tot; for (; x <= block[n - 1]; ++x) { if (x > 0) { memset(pre[x], 0, sizeof pre[x]); REP (j, k) { REP (o, j + 1) { pre[x][j] = (pre[x][j] + pre[x - 1][o] * dp[x][j - o]) % MOD; } } } else { REP (j, k) { pre[x][j] = dp[x][j]; } } } REP (j, k) { res = (res - pre[block[n - 1]][j] + MOD) % MOD; } cout << res, el; } } } struct SegmentTree { int n, k; vector<vector<int>> st; SegmentTree(int _n, int _k) { n = _n; k = _k; st.assign(4 * _n + 7, vector<int>(_k + 7, 0)); build(1, 1, n); } void build(int id, int l, int r) { if (l == r) { st[id][0] = b[l]; st[id][1] = a[l]; return; } int m = (l + r) / 2; build(id * 2, l, m); build(id * 2 + 1, m + 1, r); REP (i, k) REP (j, i + 1) { st[id][i] = (st[id][i] + st[id * 2][j] * st[id * 2 + 1][i - j]) % MOD; } } void update(int id, int l, int r, int i) { if (i < l || i > r) { return; } if (l == r) { st[id][0] = b[l]; st[id][1] = a[l]; return; } int m = (l + r) / 2; update(id * 2, l, m, i); update(id * 2 + 1, m + 1, r, i); REP (i, k) { st[id][i] = 0; REP (j, i + 1) { st[id][i] = (st[id][i] + st[id * 2][j] * st[id * 2 + 1][i - j]) % MOD; } } } void update(int i) { update(1, 1, n, i); } }; int main() { #define name "art" if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); } ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, k; cin >> n >> k; FOR (i, 1, n) { cin >> a[i]; a[i] %= MOD; } FOR (i, 1, n) { cin >> b[i]; b[i] %= MOD; } if (n <= 5000) { naive::solve(n, k); return 0; } if (n <= 5e4) { blocksqrt::solve(n, k); return 0; } int tot = 1; FOR (i, 1, n) { tot = (a[i] + b[i]) * tot % MOD; } SegmentTree seg(n, k); int q; cin >> q; while (q--) { int id, na, nb; cin >> id >> na >> nb; na %= MOD; nb %= MOD; tot = tot * inverse(a[id] + b[id]) % MOD; tot = tot * (na + nb) % MOD; a[id] = na; b[id] = nb; seg.update(id); int res = tot; REP (i, k) { res = (res - seg.st[1][i] + MOD) % MOD; } cout << res, el; } return 0; }

Compilation message (stderr)

relativnost.cpp: In function 'int main()':
relativnost.cpp:212:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  212 |         freopen(name".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
relativnost.cpp:213:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  213 |         freopen(name".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...