NOIP2017 Day1 题解
去年水平不行,导致noip滚粗,现在来复习一下,今年要小心了。
A - 小凯的疑惑
裴蜀定理。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if (ch == '-') ch = getchar(), a = -1; else a = 1; x = ch - '0'; while (ch = getchar(), ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - '0'; return a * x; } int a, b; int main() { gii(a, b); printf("%lld\n", (a - 1LL) * (b - 1LL) - 1); }
B - 时间复杂度
用个栈模拟一下。
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if (ch == '-') ch = getchar(), a = -1; else a = 1; x = ch - '0'; while (ch = getchar(), ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - '0'; return a * x; } void solve() { int L; static char fzd[233]; gi(L); scanf("%s", fzd + 1); int w = 0; if (fzd[3] == 'n') sscanf(fzd + 1, "O(n^%d)", &w); static pair<int, char> stk[233];// (x > y : -1) (x <= y : 0) (x = c, y = n : 1) int tp = 0; static bool in[233]; static int mx[233]; memset(mx, 0, sizeof mx); memset(in, 0, sizeof in); bool flag = 1; for (int i = 1; i <= L; ++i) { char ch; while (ch = getchar(), ch != 'F' && ch != 'E'); if (ch == 'F') { while (ch = getchar(), ch < 'a' || ch > 'z'); static char x[10], y[10]; scanf("%s%s", x + 1, y + 1); if (in[ch]) flag = 0; if (!flag) continue; in[ch] = 1; if (x[1] == 'n' && y[1] == 'n') { stk[++tp] = mp(0, ch); } else if (x[1] == 'n' && y[1] != 'n') { stk[++tp] = mp(-1, ch); } else if (y[1] == 'n') { stk[++tp] = mp(1, ch); } else { int X, Y; sscanf(x + 1, "%d", &X); sscanf(y + 1, "%d", &Y); if (X <= Y) stk[++tp] = mp(0, ch); else stk[++tp] = mp(-1, ch); } } else { if (!tp) flag = 0; if (!flag) continue; if (stk[tp].fi == 1) mx[tp - 1] = max(mx[tp - 1], mx[tp] + 1); else if (stk[tp].fi == 0) mx[tp - 1] = max(mx[tp - 1], mx[tp]); in[stk[tp].se] = 0; mx[tp] = 0; --tp; } } if (tp || !flag) { puts("ERR"); return; } if (mx[0] == w) { puts("Yes"); } else { //cerr << mx[0] << endl; puts("No"); } } int main() { int T; gi(T); while (T--) solve(); }
C - 逛公园
用最短路算法判断哪些点一定不会走到,先删除掉,接着建出拓扑图,如果所有没有0环是一个有向无环图,判断一下就好了。(之前还写了个智障tarjan)
//waz #include <bits/stdc++.h> using namespace std; #define mp make_pair #define pb push_back #define fi first #define se second #define ALL(x) (x).begin(), (x).end() #define SZ(x) ((int)((x).size())) typedef pair<int, int> PII; typedef vector<int> VI; typedef long long int64; typedef unsigned int uint; typedef unsigned long long uint64; #define gi(x) ((x) = F()) #define gii(x, y) (gi(x), gi(y)) #define giii(x, y, z) (gii(x, y), gi(z)) int F() { char ch; int x, a; while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); if (ch == '-') ch = getchar(), a = -1; else a = 1; x = ch - '0'; while (ch = getchar(), ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - '0'; return a * x; } const int N = 1e5 + 10, M = 2e5 + 10; int n, m, k, p, lim; struct edge { int to, val; edge *next; }; struct graph { edge e[M], *la[N], *et; int d[N]; graph() { et = e; } void clear() { memset(la, 0, sizeof la); et = e; } void add(int u, int v, int w) { *++et = (edge) {v, w, la[u]}, la[u] = et; } void dijkstra(int s) { memset(d, 63, sizeof d); priority_queue<PII> pq; pq.push(mp(0, s)); d[s] = 0; while (!pq.empty()) { PII x = pq.top(); pq.pop(); if (d[x.se] != -x.fi) continue; int u = x.se; for (edge *it = la[u]; it; it = it -> next) { int v = it -> to, w = it -> val; if (d[v] > d[u] + w) { d[v] = d[u] + w; pq.push(mp(-d[v], v)); } } } } } G1, G2, G; void make_G() { G.clear(); static int ok[N]; int idt = 0; memset(ok, 0, sizeof ok); for (int i = 1; i <= n; ++i) if (G1.d[i] + G2.d[i] <= lim + k) ok[i] = ++idt; for (int i = 1; i <= n; ++i) { if (ok[i]) { for (edge *it = G1.la[i]; it; it = it -> next) { if (ok[it -> to]) G.add(i, it -> to, it -> val); } } } n = idt; } int id[N][51]; int f[N * 51], deg[N * 51]; struct eg { int to; eg *next; }; void solve() { giii(n, m, k), gi(p); G1.clear(), G2.clear(); for (int i = 1; i <= m; ++i) { int a, b, c; giii(a, b, c); G1.add(a, b, c); G2.add(b, a, c); } lim = G1.d[n]; make_G(); G.dijkstra(1); int idt = 0; static eg e[M * 51], *la[N * 51]; eg *et = e; for (int i = 1; i <= n; ++i) for (int j = 0; j <= k; ++j) id[i][j] = ++idt, la[idt] = 0, f[idt] = deg[idt] = 0; for (int i = 1; i <= n; ++i) { for (edge *it = G.la[i]; it; it = it -> next) { int j = it -> to; for (int l = 0; l <= k; ++l) { int u = id[i][l]; int dis = G.d[i] + l + (it -> val) - G.d[j]; if (dis <= k && dis >= 0) { int v = id[j][dis]; *++et = (eg) {v, la[u]}, la[u] = et; ++deg[v]; } } } } static int q[N * 51]; int l = 0, r = 0; for (int i = 1; i <= idt; ++i) if (!deg[i]) q[r++] = i; f[id[1][0]] = 1; while (l < r) { int u = q[l++]; for (eg *it = la[u]; it; it = it -> next) { int v = it -> to; f[v] = (f[v] + f[u]) % p; --deg[v]; if (!deg[v]) q[r++] = v; } } int ans = 0; for (int i = 0; i <= k; ++i) ans = (ans + f[id[n][i]]) % p; if (r != idt) { puts("-1"); return; } printf("%d\n", ans); } int main() { int T; gi(T); while (T--) solve(); }