YACS 2023年9月月赛 乙组 题解
T1
折半水题,不多说了,代码:
#include <bits/stdc++.h> #define For(i, a, b) for (int i = (a); i <= (b); i ++) #define int long long using namespace std; int n; int a[41]; vector <int> v1, v2; void dfs1 (int x, int s) { if (x == n / 2 + 1) { v1.push_back (s); return; } dfs1 (x + 1, s + a[x]); dfs1 (x + 1, s); } void dfs2 (int x, int s) { if (x == n + 1) { v2.push_back (s); return; } dfs2 (x + 1, s + a[x]); dfs2 (x + 1, s); } signed main () { cin >> n; For (i, 1, n) cin >> a[i]; if (n == 1) { cout << (a[1] > 0); return 0; } dfs1 (1, 0); dfs2 (n / 2 + 1, 0); sort (v1.begin (), v1.end () ); sort (v2.begin (), v2.end (), greater <int> () ); int ans = 0, r = -1; For (i, 0, v1.size () - 1) { while (r != v2.size () - 1 && v2[r + 1] + v1[i] > 0) ++ r; ans += r + 1; } cout << ans; return 0; }
T2
在 NFLS 集训完后遇到的第一个是需要用我在 NFLS 学到的套路的题。
类似 dijkstra 的做法每次取出当前路径上经过障碍物最少的那个点,更新周围的点,其实就是把地图抽象成了一个最短路问题。
代码:
#include <bits/stdc++.h> #define For(i, a, b) for (int i = (a); i <= (b); i ++) #define int long long using namespace std; int n, m; char a[1005][1005]; int f[1005][1005]; const int dx[5] = {0, 1, -1, 0, 0}, dy[5] = {0, 0, 0, 1, -1}; struct Node { int x, y, c; bool operator < (const Node &s) const {return c > s.c;} }; priority_queue <Node> q; signed main () { memset (f, 0x3f, sizeof f); cin >> n >> m; For (i, 1, n) For (j, 1, m) cin >> a[i][j]; q.push ({1, 1, 0}); f[1][1] = 0; while (!q.empty () ) { int x = q.top ().x, y = q.top ().y, c = q.top ().c; q.pop (); For (i, 1, 4) { int fx = x + dx[i], fy = y + dy[i]; if (fx < 1 || fy < 1 || fx > n || fy > m) continue; int cur = f[x][y] + (a[fx][fy] == '*'); if (f[fx][fy] > cur) { f[fx][fy] = cur; q.push ({fx, fy, cur}); } } } cout << f[n][m]; return 0; }
T3
题面明显提示是一道拓扑排序,建好图之后求一遍有向无环图最长路即可,就是个 DP。
代码:
#include <bits/stdc++.h> #define For(i, a, b) for (int i = (a); i <= (b); i ++) #define int long long using namespace std; int n, m, ans; int d[200005], f[200005], t[200005]; vector <int> G[200005], e[200005]; queue <int> q; signed main () { cin >> n >> m; For (i, 1, n) cin >> t[i]; For (i, 1, m) { int x, y; cin >> x >> y; G[x].push_back (y); e[y].push_back (x); d[y] ++; } For (i, 1, n) if (d[i] == 0) q.push(i); while (!q.empty () ) { int u = q.front (); q.pop (); f[u] = t[u]; for (int v : e[u]) f[u] = max (f[u], f[v] + t[u]); ans = max (ans, f[u]); for (int v : G[u]) { d[v] --; if (d[v] == 0) q.push (v); } } cout << ans; return 0; }
T4
好题,观察到 $m$ 很小,但是我不知道该怎么做,于是就打了表过了。
代码:
#include <bits/stdc++.h> #define For(i, a, b) for (int i = (a); i <= (b); i ++) #define int long long using namespace std; int n, m; int pre[101] = {1, 682498929,491101308,76479948,723816384,67347853,27368307,625544428,199888908,888050723,927880474,281863274,661224977,623534362,970055531,261384175,195888993,66404266,547665832,109838563,933245637,724691727,368925948,268838846,136026497,112390913,135498044,217544623,419363534,500780548,668123525,128487469,30977140,522049725,309058615,386027524,189239124,148528617,940567523,917084264,429277690,996164327,358655417,568392357,780072518,462639908,275105629,909210595,99199382,703397904,733333339,97830135,608823837,256141983,141827977,696628828,637939935,811575797,848924691,131772368,724464507,272814771,326159309,456152084,903466878,92255682,769795511,373745190,606241871,825871994,957939114,435887178,852304035,663307737,375297772,217598709,624148346,671734977,624500515,748510389,203191898,423951674,629786193,672850561,814362881,823845496,116667533,256473217,627655552,245795606,586445753,172114298,193781724,778983779,83868974,315103615,965785236,492741665,377329025,847549272,698611116}; const int mod = 1000000007; int fac (int x) { int res = pre[x / 10000000]; For (i, x / 10000000 * 10000000 + 1, x) { res *= i; res %= mod; } return res; } int q_pow (int x, int y) { if (y == 0) return 1; if (y & 1) return x * q_pow (x * x % mod, y >> 1) % mod; return q_pow (x * x % mod, y >> 1); } signed main () { cin >> n >> m; cout << fac (n) * q_pow (fac (m), mod - 2) % mod * q_pow (fac (n - m), mod - 2) % mod; return 0; }