CCPC-Wannafly 夏季欢乐赛 题解
博主又復活了(因為文化課作業太多寫不完了所以繼續自爆自棄
A.完全k叉樹
簽到題,考慮最底層的點的距離即可,注意細節(成功拉低了平均通過率)
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007;inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }int main() {int T = read();while (T--) {LL k = read(), n = read(), x = 1, now = 1, cnt = 0;if (k == 1) {printf("%d\n", n - 1);continue;}while (x < n) {cnt++;now *= k;x += now;}x -= now;cnt--;LL ans = 0, lft = n - x;if (lft <= now / k) ans = max(cnt * 2 + 1, lft == 1 ? 1LL : 2LL);else ans = cnt * 2 + 2;printf("%d\n", ans);}return 0; }B.距離產生美
簽到題,每次當且僅當∣ai?ai?1∣<k|a_i-a_{i-1}|<k∣ai??ai?1?∣<k時,把aia_iai?改成infinfinf
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; const int N = 100010;int a[N], used[N]; inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }int main() {int n = read(), k = read(), ans = 0;For(i, 1, n) a[i] = read();For(i, 2, n) {if (abs(a[i] - a[i - 1]) < k && !used[i - 1]) {ans++;used[i] = 1;}}printf("%d\n", ans);return 0; }C.烤面包片
簽到題,mod≤1e9,4!!>1e9mod\leq 1e9,4!!>1e9mod≤1e9,4!!>1e9所以只需考慮n≤3n\leq 3n≤3的情況,其他都輸出000,注意0!!!=10!!!=10!!!=1
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007;inline int mul(int x, int y, int M) {return (int)(1LL * x * y % M);} inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }int main() {int n = read(), M = read();if (n == 0 || n == 1) printf("%d\n", 1 % M);else if (n == 2) printf("%d\n", 2 % M);else if (n == 3) {int now = 1;For(i, 1, 720) now = mul(now, i, M);printf("%d\n", now);}else puts("0");return 0; }D.茶顏悅色
普通題,將y坐標離散對x這一維線性枚舉長度為k的所有點,對y這一維用掃描線維護只對[y-k,y]有貢獻,時間復雜度O(nlog?n)\mathcal{O(n\log n)}O(nlogn)(給茶顏悅色打廣告可還行
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int N = 100010; struct Point {int x, y; }p[N]; struct Node {Node *ls, *rs;int tag, v;Node() {ls = rs = 0;tag = v = 0;} }*root; int py[N << 1], cnty;inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }inline bool cmp(Point a, Point b) {return a.x < b.x || a.x == b.x && a.y < b.y; }inline void pushdown(Node *&rt) {if (!rt -> ls) rt -> ls = new Node();if (!rt -> rs) rt -> rs = new Node();rt -> ls -> v += rt -> tag;rt -> rs -> v += rt -> tag;rt -> ls -> tag += rt -> tag;rt -> rs -> tag += rt -> tag;rt -> tag = 0; }inline void pushup(Node *&rt) {rt -> v = max(rt -> ls -> v, rt -> rs -> v); }inline void modify(int l, int r, int L, int R, int val, Node *&rt) {if (!rt) rt = new Node();if (r < L || R < l) return;if (L <= l && r <= R) {rt -> tag += val;rt -> v += val;return;}int mid = l + r >> 1;pushdown(rt);modify(l, mid, L, R, val, rt -> ls); modify(mid + 1, r, L, R, val, rt -> rs);pushup(rt); }int main() {int n = read(), k = read();py[++cnty] = 1;For(i, 1, n) {p[i].x = read(), p[i].y = read();py[++cnty] = p[i].y;py[++cnty] = p[i].y - k;}sort(py + 1, py + cnty + 1);int ny = unique(py + 1, py + cnty + 1) - py - 1;sort(p + 1, p + n + 1, cmp);int l = 1, r = 1;for(; r <= n; ++r) {if (p[r].x - p[l].x > k) break;modify(1, ny, lower_bound(py + 1, py + ny + 1, p[r].y - k) - py, lower_bound(py + 1, py + ny + 1, p[r].y) - py, 1, root);}int ans = 0;for(; r <= n; ++r) {ans = max(ans, root -> v);for(; p[r].x - p[l].x > k; ++l) modify(1, ny, lower_bound(py + 1, py + ny + 1, p[l].y - k) - py, lower_bound(py + 1, py + ny + 1, p[l].y) - py, -1, root);modify(1, ny, lower_bound(py + 1, py + ny + 1, p[r].y - k) - py, lower_bound(py + 1, py + ny + 1, p[r].y) - py, 1, root);}ans = max(ans, root -> v);printf("%d\n", ans);return 0; }E.飛行棋
普通題,考慮在[d?k,d?1][d-k,d-1][d?k,d?1]中的每一個位置都有1k\frac{1}{k}k1?的概率到達終點,還有k?1k\frac{k-1}{k}kk?1?的概率到達另一個[d?k,d?1][d-k,d-1][d?k,d?1]的點,所以期望步數是kkk。從終點出發逆向dp,dp[x]=k(x∈[1,k]),dp[x]=1+1k∑i=x?kx?1dp[i]dp[x]=k(x\in [1,k]),dp[x]=1+\frac{1}{k}\sum_{i=x-k}^{x-1}dp[i]dp[x]=k(x∈[1,k]),dp[x]=1+k1?∑i=x?kx?1?dp[i],由于d較大,使用矩陣加速即可。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; const int N = 25;int K, inv; inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }inline void upd(int &x, int y) {x += y; x -= x >= MOD ? MOD : 0;} inline int dec(int x, int y) {x -= y; x += x < 0 ? MOD : 0; return x;} inline int add(int x, int y) {x += y; x -= x >= MOD ? MOD : 0; return x;} inline int mul(int x, int y) {return 1LL * x * y % MOD;};inline int qui_pow(int x, int y) {int ret = 1;for(; y; y >>= 1) {if (y & 1) ret = mul(ret, x);x = mul(x, x);}return ret; }struct Matrix {int num[N][N];Matrix operator * (const Matrix &A) const {Matrix ret;memset(ret.num, 0, sizeof ret.num);For(i, 1, K) For(j, 1, K) For(k, 1, K) upd(ret.num[i][j], mul(num[i][k], A.num[k][j]));return ret;} }init, cha;inline Matrix mat_pow(Matrix x, LL y) {Matrix ret;memset(ret.num, 0, sizeof ret.num);For(i, 1, K) ret.num[i][i] = 1;for(; y; y >>= 1) {if (y & 1) ret = ret * x;x = x * x;}return ret; }int main() {LL d = read();K = read(), inv = qui_pow(K, MOD - 2);For(i, 1, K) init.num[1][i] = K, cha.num[i][1] = inv;init.num[1][K + 1] = cha.num[K + 1][1] = cha.num[K + 1][K + 1] = 1;For(i, 2, K) cha.num[i - 1][i] = 1;K++;init = init * mat_pow(cha, d - K + 1);printf("%d\n", init.num[1][1]);return 0; }F.三元組
普通題,假設ai+aj≤bi+bja_i+a_j\leq b_i+b_jai?+aj?≤bi?+bj?,所以2(ai+aj)≤bi+bj,2ai?bi+2aj?bj≤02(a_i+a_j)\leq b_i +b_j,2a_i-b_i+2a_j-b_j\leq 02(ai?+aj?)≤bi?+bj?,2ai??bi?+2aj??bj?≤0,只需按2ai?bi2a_i-b_i2ai??bi?排序即可,ai+aj≥bi+bja_i+a_j\geq b_i+b_jai?+aj?≥bi?+bj?亦然
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; const int N = 100010;inline void upd(int &x, int y) {x += y; x -= x >= MOD ? MOD : 0;} inline int dec(int x, int y) {x -= y; x += x < 0 ? MOD : 0; return x;} inline int add(int x, int y) {x += y; x -= x >= MOD ? MOD : 0; return x;} inline int mul(int x, int y) {return 1LL * x * y % MOD;};inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }struct Node {int a, b, c, v; }p[N]; int v[N], sum[N], n;inline bool cmp(Node x, Node y) {return x.v < y.v;}inline int solve() {int ret = 0;For(i, 1, n) p[i].v = 2 * p[i].a - p[i].b;sort(p + 1, p + n + 1, cmp);sum[0] = v[0] = 0;For(i, 1, n) {v[i] = p[i].v;sum[i] = add(sum[i - 1], p[i].c);upd(ret, mul(sum[upper_bound(v + 1, v + i + 1, -v[i]) - v - 1], p[i].c));}return ret; }int main() {n = read();For(i, 1, n) p[i].a = read(), p[i].b = read(), p[i].c = read();int ans = solve();For(i, 1, n) swap(p[i].a, p[i].b);upd(ans, solve());printf("%d\n", ans);return 0; }G.籃球校賽
簽到題,直接狀壓dp,時間復雜度O(5?25n)\mathcal{O(5* 2^5 n)}O(5?25n)
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; const int N = 100010;inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }LL dp[N][32], a[N][5];int main() {int n = read();For(i, 1, n) For(j, 0, 4) a[i][j] = read();For(i, 1, n) {For(j, 0, 31) {For(k, 0, 4) {if ((j >> k) & 1) dp[i][j] = max(dp[i - 1][j ^ (1 << k)] + a[i][k], dp[i][j]);dp[i][j] = max(dp[i - 1][j], dp[i][j]);}}}printf("%lld\n", dp[n][31]);return 0; }H.分配學號
簽到題,先排序確定最終的學號集合,易證明集合是唯一的,從大到小枚舉可能,運用乘法原理和加法原理求得答案
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007; const int N = 100010; inline void upd(int &x, int y) {x += y; x -= x >= MOD ? MOD : 0;} inline int dec(int x, int y) {x -= y; x += x < 0 ? MOD : 0; return x;} inline int add(int x, int y) {x += y; x -= x >= MOD ? MOD : 0; return x;} inline int mul(int x, int y) {return 1LL * x * y % MOD;}LL a[N], b[N]; int ans = 1, cnt[N];inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }int main() {int n = read();For(i, 1, n) a[i] = read();sort(a + 1, a + n + 1);memcpy(b, a, sizeof b);For(i, 2, n) {if (a[i] <= a[i - 1]) a[i] = a[i - 1] + 1, cnt[i] = cnt[i - 1] + 1;}int now = 0, maxi = 0, ret = 1;Rep(i, n, 1) {if (!cnt[i]) {ans = mul(ans, ret);now = maxi = 0;continue;}if (!now) now = cnt[i], maxi = a[i], ret = 1;ret = mul(ret, maxi - b[i] + 1 - now + cnt[i]);}printf("%d\n", ans);return 0; }I.Gree的心房
簽到題,留出最短的一條路徑,可見障礙物最多填充(n?1)×(m?1)(n-1)\times(m-1)(n?1)×(m?1)個位置,超過這個值就輸出-1,否則輸出n+m-2
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define Mp make_pair #define Pi pair<int, int> #define Pb push_back #define Fi first #define Se second #define Gc getchar #define LL long long #define Res register int #define For(i, l, r) for(int i = (int)(l); i <= (int)(r); ++i) #define Rep(i, r, l) for(int i = (int)(r); i >= (int)(l); --i)using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1000000007;inline LL read(){LL x = 0;char ch = Gc();bool positive = 1;for (; !isdigit(ch); ch = Gc()) if (ch == '-') positive = 0;for (; isdigit(ch); ch = Gc()) x = (x << 1) + (x << 3) + (ch ^ 48);return positive ? x : -x; }int main() {int n = read(), m = read(), k = read();LL all = 1LL * (n - 1) * (m - 1);if (k <= all) printf("%d\n", n + m - 2);else puts("-1");return 0; }比賽總結:jwj是有gf的人生贏家!我也要!
總結
以上是生活随笔為你收集整理的CCPC-Wannafly 夏季欢乐赛 题解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tomcat学习笔记(JDK+TOMCA
- 下一篇: Comet OJ 2019 夏季欢乐赛题