20267.25 考试总结
考试总结
估:100 + 100 + 0 + 100
得:100 + 100 + 0 + 100 rk2
666 t4 怎么数据这么水。
状态好拉这 t3 没做出来。
matrix
加强自 Sky Reflector。
首先转换充要条件,注意到对于 \(\max_i \{a_i\} \le \min_i \{b_i\}\) 得情况一定能构造出合法矩阵,于是直接计数,枚举 \(b\) 得最小值 \(x\),有:
做完了,用线性筛预处理幂可以做到 \(O(n)\)。
code
#include <bits/stdc++.h>
using namespace std;
#define int ll
#define ll long long
#define usd unsigned
#define el putchar('\n')
#define lowbit(x) (x & (-x))
#define AC return
#define AK return 0
#define YS cout << "YES"
#define NO cout << "NO"
#define Ys cout << "Yes"
#define No cout << "No"
#define ys cout << "yes"
#define no cout << "no"
#define ls(i) ch[i][0]
#define rs(i) ch[i][1]
#define debug(num) cerr << #num << ' ' << num << '\n'
#define void inline void
#define il inline
#define Mod(x) (((x) % mod + mod) % mod)
#define pii pair <int, int>
#define pll pair <ll, ll>
il char gc() { char c; while((c = getchar()) <= ' ') ; return c; }
il int rd() {
char c; int x, f = 1;
while(!isdigit(c = getchar())) if(c == '-') f *= -1;
x = c ^ 48;
while(isdigit(c = getchar())) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
void ACehomoxue();
signed main() {
srand(time(0));
// freopen("matrix.in", "r", stdin);
// freopen("matrix.out", "w", stdout);
int t = 1;
// t = rd();
while(t--) ACehomoxue();
AK;
}
const int mod = 998244353, maxn = 3 * 1e7 + 18;
int n, m, k, ans = 0;
il int ksm(int a, int k = mod - 2) { int res = 1; for(; k; k >>= 1, a = a * a % mod) if(k & 1) res = res * a % mod; return res; }
vector <int> prime;
bool vis[maxn];
int qpn[maxn], qpm[maxn];
void pre() {
qpn[1] = qpm[1] = 1;
for(int i = 2; i < maxn; i++) {
if(!vis[i]) {
qpn[i] = ksm(i, n);
qpm[i] = ksm(i, m);
prime.push_back(i);
}
for(int p : prime) {
if(i * p >= maxn) break;
vis[i * p] = true;
qpn[i * p] = qpn[i] * qpn[p] % mod;
qpm[i * p] = qpm[i] * qpm[p] % mod;
if(i % p == 0) break;
}
}
}
void ACehomoxue() {
n = rd(), m = rd(), k = rd();
if(n == 1) { cout << ksm(k, m); el; AC; }
if(m == 1) { cout << ksm(k, n); el; AC; }
pre();
for(int x = 1, tmp; x <= k; x++) {
tmp = (qpm[k - x + 1] + mod - qpm[k - x]) % mod * qpn[x] % mod;
ans = (ans + tmp) % mod;
}
cout << ans;
el;
}
caterpillar
改编自 Tree Queries。
我们先考虑暴力,考虑从 \(1\) 开始设计到 \(v\) 的路线,假设确定了在 \(x\) 得子树中,那么若对于 \(x\) 的一个儿子 \(u\) 中最大的关键点深度为 \(mx_u\),那么如果不在 \(u\) 中那么就有 \(k \gets \max(k, mx_u - dep_x)\)。由于 \(k\) 要尽量小那么 \(v\) 就应在 \(mx_u\) 最大的 \(u\) 里,然后再到 \(u\) 的子树中找可以做到 \(O(n ^ 2)\)。考虑这些贡献只和关键点有关,于是拉出虚树做即可。做完了。
code
#include <bits/stdc++.h>
using namespace std;
#define int int
#define ll long long
#define usd unsigned
#define el putchar('\n')
#define lowbit(x) (x & (-x))
#define AC return
#define AK return 0
#define YS cout << "YES"
#define NO cout << "NO"
#define Ys cout << "Yes"
#define No cout << "No"
#define ys cout << "yes"
#define no cout << "no"
#define ls(i) ch[i][0]
#define rs(i) ch[i][1]
#define debug(num) cerr << #num << ' ' << num << '\n'
#define void inline void
#define il inline
#define Mod(x) (((x) % mod + mod) % mod)
#define pii pair <int, int>
#define pll pair <ll, ll>
il char gc() { char c; while((c = getchar()) <= ' ') ; return c; }
il int rd() {
char c; int x, f = 1;
while(!isdigit(c = getchar())) if(c == '-') f *= -1;
x = c ^ 48;
while(isdigit(c = getchar())) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
void ACehomoxue();
signed main() {
srand(time(0));
// freopen("caterpillar.in", "r", stdin);
// freopen("caterpillar.out", "w", stdout);
int t = 1;
// t = rd();
while(t--) ACehomoxue();
AK;
}
const int mod = 998244353, maxn = 1e6 + 18, maxk = 21;
int n, q, dep[maxn], in[maxn], dfn, nxt[maxn][maxk];
vector <int> vec[maxn], s;
void dfs(int x, int fa) {
in[x] = ++dfn;
dep[x] = dep[fa] + 1;
nxt[x][0] = fa;
for(int i = 1; i < maxk; i++) nxt[x][i] = nxt[nxt[x][i - 1]][i - 1];
for(int to : vec[x]) if(to != fa) dfs(to, x);
}
il int lca(int u, int v) {
if(dep[u] > dep[v]) swap(u, v);
for(int i = maxk - 1; i + 1; i--) if(dep[nxt[v][i]] >= dep[u]) v = nxt[v][i];
if(u == v) return u;
for(int i = maxk - 1; i + 1; i--) if(nxt[u][i] != nxt[v][i]) u = nxt[u][i], v = nxt[v][i];
return nxt[u][0];
}
il bool cmp(const int &a, const int &b) { return in[a] < in[b]; }
class vt {
vector <int> vec[maxn];
bool vis[maxn];
int mx[maxn], ans = 0;
void clr(vector <int> &v) { for(int x : v) vec[x].clear(), vis[x] = false, mx[x] = 0; v.clear(); }
void pre(int x) {
for(int to : vec[x]) {
pre(to);
mx[x] = max(mx[x], mx[to]);
}
}
void dfs(int x) {
int fir = 0, sec = 0;
for(int to : vec[x]) {
if(mx[to] >= mx[fir]) sec = fir, fir = to;
else if(mx[to] > mx[sec]) sec = to;
}
if(!fir) AC;
ans = max(ans, mx[sec] - dep[x]);
dfs(fir);
}
public:
il int sol(vector <int> &p) {
ans = 0;
for(int x : p) { vis[x] = true; if(x != 1) mx[x] = dep[x]; }
sort(p.begin(), p.end(), cmp);
for(int i = 1, u, v, pa; i < (int) p.size(); i++) {
u = p[i - 1], v = p[i], pa = lca(u, v);
if(!vis[pa]) vis[pa] = true, p.push_back(pa);
}
sort(p.begin(), p.end(), cmp);
for(int i = 1, u, v, pa; i < (int) p.size(); i++) {
u = p[i - 1], v = p[i], pa = lca(u, v);
if(pa != v) vec[pa].push_back(v);
}
pre(p[0]);
dfs(p[0]);
clr(p);
return ans;
}
} ds;
void ACehomoxue() {
n = rd(), q = rd();
for(int i = 1, u, v; i < n; i++) {
u = rd(), v = rd();
vec[u].push_back(v);
vec[v].push_back(u);
}
dfs(1, 0);
for(int t; q--; ) {
t = rd();
s.clear();
s.push_back(1);
for(int x; t--; ) {
x = rd();
s.push_back(x);
}
cout << ds.sol(s);
el;
}
}
/*
g++ -std=c++14 -O2 -o output/caterpillar.exe caterpillar.cpp && cd output && start checker.exe && cd..
*/
nothingness
原:Conveyor。
考虑差分第 \(t\) 秒和第 \(t - 1\) 秒计算 \((x, y)\) 上经过的次数来看第 \(t\) 秒是否有史莱姆经过,现在就是求前 \(t\) 秒 \((x, y)\) 经过多少次。显然要走 \(x + y\) 次才能到 \((x, y)\),那么只会有 \(t + 1 - x - y\) 个点会有贡献,那么我们令 \(f_{0, 0} = t + 1 - x - y\) 表示可能贡献的经过次数。对于任意的 \(f_{i, j}\),显然其对 \(f_{i + 1, j}\) 的贡献为 \(\lfloor \frac {f_{i, j}} 2 \rfloor\) 而对 \(f_{i, j + 1}\) 贡献有 \(\lceil \frac {f_{i, j}} 2 \rceil\),直接递推到 \(f_{x, y}\) 即可。做完了。
training
楼房重建玩耍。考虑直接线段树维护,发现其实维护是简单的,其 push_up() 类似楼房重建的二分,区间修改也都是好维护的。对于查询,我们分两种,一是走到 \(v\) 最大后还能走,直接除一除即可。对于走不到 \(v\) 最大的地方,设位置为 \(p\),那么把 \([s, p]\) 的线段树节点领出来二分即可。
做完了,时间复杂度 \(O(n \log ^ 2n)\)。
就是懒得写。

浙公网安备 33010602011771号