DDJ Regular Contest Round#6 Tutorial
a624 A. Benson 的數學課
可以從前幾項來推測答案是 ,接著嚴謹證明如下:
step 1.
若 ,得分為 ,命題成立。
step 2.
設 時,根據歸納假設將 拆成任意 滿足 且 ,由於 ,所以可從歸納法得到兩項最後分別會是 分,以及現在得到的 分,加起來 ,因此式子成立,得證。
a630 B. Benson 的體育課
可以發現答案有以下關係式:
這有證明
https://math.stackexchange.com/questions/2392795/domino-tiling-on-a-3-by-n-rectangle
由於 ,可用矩陣快速冪優化做到複雜度在 的時間完成。
由於方便且再優化常數可以先判斷奇偶,只對偶數做矩陣快速冪。
a631 C. Benson 的福利社
其實就是求序列的中位數而已,如果 是偶數,則 的整數都是答案。
這有證明
https://math.stackexchange.com/questions/113270/the-median-minimizes-the-sum-of-absolute-deviations-the-ell-1-norm
a632 D. Benson 的美術課
帶修改莫隊經典問題,時間複雜度為 。
後來發現沒有卡好數字範圍,可以用 bitset 唬爛過去 QQ。
程式碼代補
a516 E. Benson 的 LCM
線段樹裸題,不過因為數字範圍頗大,需要使用動態開點再帶上懶標記,如果一個區間只有一個數字的話,就標記它,該區間不再往下遞迴建構,以此類推,下次經過時再下放一層。
#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;
#define gcd __gcd
using ll = long long;
ll N;
struct node {
node *l, *r; ll v, tag;
void pull() {
ll g = gcd(l ? l->v : 1LL, r ? r->v : 1LL);
v = (l ? l->v : 1LL) * (r ? r->v : 1LL) / g;
}
void push(ll l, ll r) {
ll m = (l + r) >> 1;
if (tag <= m) this->l = new node(v, tag);
else this->r = new node(v, tag);
tag = -2;
}
node(ll _v = 1, ll _tag = -1): v(_v), tag(_tag) {
l = r = nullptr;
}
} *root = nullptr;
void upd(node*& o, ll x, ll v, ll l = 1LL, ll r = N) {
if (!o) o = new node;
if (o->tag == x || l == r) {
o->v = v;
return;
}
if (o->tag == -1) {
o->tag = x, o->v = v;
return;
}
if (o->tag > 0) o->push(l, r);
ll m = (l + r) >> 1;
if (x <= m) upd(o->l, x, v, l, m);
else upd(o->r, x, v, m + 1, r);
o->pull();
}
ll qry(node* o, ll ql, ll qr, ll l = 1LL, ll r = N) {
if (!o) return 1;
if (ql <= l && r <= qr) return o->v;
if (o->tag > 0) return ql <= o->tag && o->tag <= qr ? o->v : 1;
ll m = (l + r) >> 1, lret = 0, rret = 0;
if (ql <= m) lret = qry(o->l, ql, qr, l, m);
if (qr > m) rret = qry(o->r, ql, qr, m + 1, r);
ll g = gcd(lret ? lret : 1LL, rret ? rret : 1LL);
return (lret ? : 1LL) * (rret ? : 1LL) / g;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int Q; cin >> N >> Q;
while (Q--) {
int op; cin >> op;
if (op == 1) {
ll x, v; cin >> x >> v;
upd(root, x, v);
}
else {
ll ql, qr; cin >> ql >> qr;
cout << qry(root, ql, qr) << '\n';
}
}
}