usingnamespace std; using longs = longlong; using uint = unsigned;
inlineintnextInt() { int x = 0, f = 1, ch = getchar(); while (!isdigit(ch)) if (ch == '-') f = -1, ch = getchar(); while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar(); return x * f; }
inline longs gcd(longs a, longs b) { if (a < b) swap(a, b); if (!b) return a; elsereturngcd(b, a % b); }
while (cin >> a >> b) if (a.length() == b.length()) { if (a == b) cout << '=' << endl; elseif (a < b) cout << '<' << endl; else cout << '>' << endl; } else { longs _a = a.length(), _b = b.length(); longs ca = 0, cb = 0, cnt = 0; longs lim = _a + _b - gcd(_a, _b); while (cnt < lim) { if (a[ca] != b[cb]) break; ca = (ca + 1) % _a; cb = (cb + 1) % _b; ++ cnt; } if (cnt == lim) cout << '=' << endl; elseif (a[ca] < b[cb]) cout << '<' << endl; else cout << '>' << endl; }
return0; }
那么什么是 Periodicity Lemma 呢?
关于 Periodicity Lemma
周期引理:字符串 S 有循环节 p 和 q 并满足 p + q ≤ |S| + gcd(p, q),那么 gcd(p, q) 也是一个循环节;
在这一题里的用法?
显然,a 和 b 是待比较字符串(现设为 A 和 B,长度为 ∞)的循环节;我们先假设 A = B = S,那么 a 和 b 都是 S 的循环节;因为 |S| = ∞,所以 a + b - gcd(a, b) ≤ |S| 可以使用周期引理:gcd(a, b) 是 S 的循环节;因为串 gcd(a, b) 较短,它成为了循环节,则整个串显然相同;
如果 A,B 的前 a + b - gcd(a, b) 位不相同,则不能被看作是一个字符串,上述假设就失效了;这时也可以判定字符串的字典序大小,直接输出即可;
简单的说,若两个字符串相等的假设成立,那么就一定可以证明 gcd(a, b) 长度的字串是循环节,这个串的长度小于 a 和 b,且再使用引理的过程中已经判等了,所以两个串相等,假说也成立;
usingnamespace std; using longs = longlong; using uint = unsigned;
inlineintnextInt() { int x = 0, f = 1, ch = getchar(); while (!isdigit(ch)) if (ch == '-') f = -1, ch = getchar(); while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar(); return x * f; }
const longs mod = 998244353; const longs p = mod - 2;
intfracMod(longs a, longs b)// 费马小定理法 { auto n = p; longs ans = 1; while (n) { if (n & 1) ans = (ans * b) % mod; b = (b * b) % mod; n >>= 1; } ans = (ans * a) % mod; return (int) ans; }
constint N = 1e6 + 5; longs ans[N];
auto init = [] { longs a = 1, b = 1; for (longs i = 1; i < N; ++ i) { a = (a * i) % mod; b = (2 * b * (2 * i + 1)) % mod; ans[i] = fracMod(a, b); } };