#include<bits/stdc++.h> usingnamespace std; #define ll long long constint INF = 0x3f3f3f3f; const ll inf = 0x3f3f3f3f3f3f3f3f; const ll mod = 998244353; constint N = 2e6 + 10; char a[N], b[N]; intck(){ int n = max((int)strlen(a), (int)strlen(b)); int p = (int)strlen(a), q = (int)strlen(b); for (int i = 0; i < 2*n; i++) { if (a[i%p] != b[i%q]) { if (a[i%p] < b[i%q])return-1; elsereturn1; } } return0; } intmain(){ while (scanf("%s%s", a, b) == 2) { int ans = ck(); if (ans == -1)puts("<"); elseif (ans == 0)puts("="); elseputs(">"); } return0; }
#include<bits/stdc++.h> usingnamespace std; #define ll long long constint INF = 0x3f3f3f3f; const ll inf = 0x3f3f3f3f3f3f3f3f; const ll mod = 998244353; constint N = 1010; typedef pair<int, int>pii;
int co[N];
structE { int from, to, cp, v; int rev; E() {} E(int f, int t, int cp, int v, int rev) :from(f), to(t), cp(cp), v(v), rev(rev) {} }; structMCMF { int n, m, s, t; vector<E> edges; vector<int> G[N]; bool inq[N]; //是否在队列 int d[N]; //Bellman_ford单源最短路径 int p[N]; //p[i]表从s到i的最小费用路径上的最后一条弧编号 int a[N]; //a[i]表示从s到i的最小残量 voidinit(int _n, int _s, int_t){ n = _n; s = _s; t = _t; for (int i = 1; i <= n; i++) G[i].clear(); edges.clear(); m = 0; }
voidaddedge(int from, int to, int cap, int cost){ edges.push_back(E(from, to, cap, cost, 0)); edges.push_back(E(to, from, 0, -cost, 1)); G[from].push_back(m++); G[to].push_back(m++); }
boolBellmanFord(int &flow, int &cost){ for (int i = 1; i <= n; i++) d[i] = INF; memset(inq, 0, sizeof inq); d[s] = 0, a[s] = INF, inq[s] = true; queue<int> Q; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); inq[u] = false; for (int& idx : G[u]) { E &e = edges[idx]; if (e.cp && d[e.to] > d[u] + e.v) { d[e.to] = d[u] + e.v; p[e.to] = idx; a[e.to] = min(a[u], e.cp); if (!inq[e.to]) { Q.push(e.to); inq[e.to] = true; } } } } if (d[t] == INF) returnfalse; flow += a[t]; cost += a[t] * d[t]; int u = t; while (u != s) { edges[p[u]].cp -= a[t]; edges[p[u] ^ 1].cp += a[t]; u = edges[p[u]].from; } returntrue; }
ll gcd(ll a, ll b){ if (a < b)swap(a, b); return b == 0 ? a : gcd(b, a%b); } int n, m, q; intmain(){ while (scanf("%d%d", &n, &m) == 2) { int S = 1, T = n; MM.init(n, S, T); for (int i = 0; i < m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); MM.addedge(a, b, 1, c); } int mxf = MM.go().first; scanf("%d", &q); while (q--) { ll u, v; scanf("%lld%lld", &u, &v); if (mxf*u < v) { puts("NaN"); continue; } ll x = u * co[v / u] + (v%u)*(co[v / u + 1] - co[v / u]); ll g = gcd(x, v); printf("%lld/%lld\n", x / g, v / g); } } return0; }
A. B-Suffix Array
题意:给定一个只有 ‘A’, ‘B’ 的字符串。定义一个字符串的 B 数列的每一位为该位前面最近的和它相同字母的位置和该位置的距离,如果前面没有和它相同的字符,则为 0。对于给定字符串的每一个后缀,求出它的 B 数列,并按照 B 数列的字典序排序,输出。
结论:定义一个字符串的 C 数列,为每一位后面最近的和它相同的字母的位置的距离,如果没有则为 n,且最后一位规定为 n+1。再求 C 数列的后缀数组,倒序输出。
C 和 B 的不同之处就在于一个是后面一个是前面,可以发现 B 数列把所有同为 ‘A’ 的位置向左移动一位,同为 ‘B’ 的位置的向左移动一位,就得到了对应的 C 数列。
B 数列一定是类似 0111102 的形式,假设有两个字符串S,T,在某一位的 B 数列值第一次不同,则这一位一定一个是 ‘A’,一个是 ’B’,则不同的这一位一定有一个是 1,另一个不是 1,这样向左移动一位后由于原先在不同位的B值这时移动到了相同位,则原先 B 数列字典序小的那个串(即第一个不同位为 1 的那个串)这时 C 数列反而更小。所以求 B 数列递增就是求 C 数列递减。
而由于每个后缀的 B 数列都必须重新求,但 C 数列可以只求一次,所以问题转换为求 C 数列后,只要对整个字符串求一次 C,再对后缀排序即可。
而由于最后一位的 B 值一定是 0,所以最后一位 B 数列一定最小,也就是必须要让它的 C 数列最大,所以最后一位规定为 n+1。