rec.md
大概就是做一些省选的题吧,然后还剩下的东西大概就是会等到省选完再学吧。
省选2024 迷宫守卫
之前没有做过的,现在来补一下。
注意到第一个点是很重要的,先考虑第一个点选什么然后一个一个推下去,显然有朴素的
转移显然
关键是如何求答案。考虑定义
考虑
-
若
在右子树:那么 一定不会选,由于是先访问右子树,那么需要尽量给右子树更多的钱,于是我们预留左子树需要的钱数 ,执行 。 -
若
在左子树:考虑 是否会被选择,首先执行 。由于选择 会导致 可以直接使用的钱变少,肯定是更劣的,于是我们能不选就不选,即 时,我们才会选择 。然后执行 即可。
这样时间复杂度就是
qwq
#include<bits/stdc++.h> #define ll long long //#define int long long #define pir pair<int, ll> #define pb emplace_back #define ls (u << 1) #define rs (u << 1 | 1) #define lf(x) ((x >= (1ll << n))) #define fi first #define se second using namespace std; const int N = (1ll << 17) + 10; const ll INF = 1e18; int n; ll w[N], q[N], rk[N]; vector<pir> vec[N]; inline void dp(int u){ if(lf(u)){vec[u].pb(make_pair(q[u], 0ll)); return;} dp(ls); dp(rs); int siz = vec[ls].size() - 1; //vec[ls].pb(pINF); vec[rs].pb(pINF); int i = siz, j = siz; while(i >= 0 && j >= 0){ int val = 0; if(vec[ls][i].fi > vec[rs][j].fi) val = vec[ls][i].fi, i--; else val = vec[rs][j].fi, j--; vec[u].pb(make_pair(val, ((i != siz) ? vec[ls][i + 1].se : INF) + min(w[u], ((j != siz) ? vec[rs][j + 1].se : INF)))); } while(i >= 0) vec[u].pb(make_pair(vec[ls][i].fi, vec[ls][i].se + min(vec[rs][0].se, w[u]))), i--; while(j >= 0) vec[u].pb(make_pair(vec[rs][j].fi, vec[ls][0].se + min(vec[rs][j].se, w[u]))), j--; reverse(vec[u].begin(), vec[u].end()); // cerr << u << "\n"; // for(auto qwq : vec[u]) cerr << qwq.fi << " " << qwq.se << "\n"; } inline int findpos(int u, ll val){ int ret = 0, L = 0, R = vec[u].size() - 1; while(L <= R){ int mid = (L + R >> 1); if(vec[u][mid].se <= val) L = mid + 1, ret = vec[u][mid].fi; else R = mid - 1; } return ret; } inline ll getf(int u, int j){ ll ret = 0, L = 0, R = vec[u].size() - 1; while(L <= R){ int mid = (L + R >> 1); if(vec[u][mid].fi >= j) ret = vec[u][mid].se, R = mid - 1; else L = mid + 1; } if(L == vec[u].size() && (!ret)) ret = INF; // cerr << u << " " << j << " " << ret << "\n"; return ret; } inline ll sol(int u, ll k, int dep){ // cerr << u << " " << k << "\n"; if(lf(u)){cout << q[u] << " "; return 0;} int j = findpos(u, k); ll ret = 0; // cerr << u << " " << j << "\n"; if(rk[j] & (1ll << (n - dep - 1))){ ret = sol(rs, k - getf(ls, j), dep + 1); ret += sol(ls, k - ret, dep + 1); } else { ll fr = getf(rs, j); ret += sol(ls, k - min(fr, w[u]), dep + 1); if(fr > k - ret) ret += w[u]; ret += sol(rs, k - ret, dep + 1); } return ret; } inline void solve(){ ll k; cin >> n >> k; for(int i = 1; i < (1ll << n); i++) cin >> w[i]; for(int i = (1ll << n); i < (1ll << (n + 1)); i++) cin >> q[i], rk[q[i]] = i; dp(1); sol(1, k, 0); cout << "\n"; } inline void clr(){ for(int i = 1; i < (1ll << (n + 1)); i++) vec[i].clear(); } signed main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T; cin >> T; while(T--) clr(), solve(); return 0; }
ABC245Ex Product Modulo 2
经典的,我们先不考虑最后一位的取值,而是考虑前
然后考虑假设前
由于
注意
qwq
#include<bits/stdc++.h> #define ll long long //#define int long long #define pir pair<int, int> #define pb emplace_back using namespace std; const int N = 40; const ll mod = 998244353; ll n, m, A, ccb[N], pw[N]; inline void ADD(ll& x, ll y){x += y; (x >= mod) ? (x -= mod) : 0ll;} struct mat{ ll a[N + 5][N + 5]; mat(){memset(a, 0, sizeof a);} inline void I(){ for(int i = 0; i < N; i++) a[i][i] = 1; } }; inline mat operator*(struct mat A, struct mat B){ mat ret; for(int k = 0; k < N; k++) for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) ADD(ret.a[i][j], A.a[i][k] * B.a[k][j] % mod); return ret; } inline mat mpow(mat bas, ll y){ mat ans; ans.I(); for(; y; y >>= 1, bas = bas * bas) if(y & 1) ans = ans * bas; return ans; } inline ll solvesi(ll p, int mx){ //cout << p << " " << mx << "\n"; ll ans = 0; mat bas; pw[0] = 1; for(int i = 1; i <= mx; i++) pw[i] = pw[i - 1] * p; for(int i = 0; i < mx; i++) ccb[i] = (pw[mx - i] - pw[mx - i - 1]) % mod; ccb[mx] = 1; for(int i = 0; i <= mx; i++){ for(int j = 0; j <= mx; j++) ADD(bas.a[i][min(mx, i + j)], ccb[j]); } mat ret; ret.a[0][0] = 1; if(A % pw[mx] == 0){ ret = ret * mpow(bas, n); // cout << ret.a[0][mx] << "\n"; return ret.a[0][mx]; } ret = ret * mpow(bas, n - 1); for(int i = 0; i <= mx; i++){ if(A % pw[i] != 0) break; ADD(ans, ret.a[0][i] * pw[i] % mod); } return ans; } signed main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> A >> m; ll ans = 1; for(ll i = 2; i * i <= m; i++){ if(m % i == 0){ int cnt = 0; while(m % i == 0) m /= i, cnt++; ans = ans * solvesi(i, cnt) % mod; } } if(m > 1) ans = ans * solvesi(m, 1) % mod; cout << ans; return 0; }
本文作者:Little_corn
本文链接:https://www.cnblogs.com/little-corn/p/18738529
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步