* Codeforces Round 889 (Div. 2) B. Longest Divisors Interval
给一个正整数 \(n\) ,找一段最长的 \([l, r]\) ,满足 \(\forall i, i \in [l, r],\ s.t.\ i | n\) 。输出这一段区间的长度,即 \(r - l + 1\) 。
\(n\) 不超过 \(10^{18}\) 。
剩余系和公倍数相关推论题?
剩余类:
设模数为 \(n\) ,整数可根据 \(\bmod n\) 的余数划为 \(n\) 类。
若 \(x \equiv a (\bmod n)\) ,则 \(x\) 属于剩余类 \([a]\) 。
若 \(x\) 属于一个剩余类,则 \(x + tn\) 与属于这个剩余类。
完全剩余系: 从模 \(n\) 的每个剩余类中任选一个数,组成的集合叫做一个完全剩余系。
定理:连续 \(n\) 个数是一个模 \(n\) 的完全剩余系。
证明:若 \(k, k + 1, k + 2, \cdots, k + n - 1\) 不是模 \(n\) 的完全剩余系,则 \(\exists i, j\ s.t.\ 0 \leq i < j \leq n - 1\) 有 \(k + i \equiv k + j (\bmod n)\) ,即 \(n \mid i - j\) 。显然 \(1 \leq i - j \leq n - 1\) 而矛盾。\(\square\)
推论1:连续 \(n\) 个数 \(k, k + 1, k + 2, \cdots, k + n - 1\) , \(\exists n \mid x\ s.t.\ k \leq x \leq k + n - 1\) 。
证明:连续 \(n\) 个数 \(l, l + 1, l + 2, \cdots, l + n - 1\) 组成一个模 \(n\) 的完全剩余系,于是 \(\exists x \in [0]\ s.t.\ l \leq x \leq l + n - 1\) 。又 \([0] = 0 + tn\) ,于是 \(n \mid x\) 。\(\square\)
推论2:\(\forall l \geq 1, lcm(1, 2, 3, \cdots, k) \mid lcm(l, l + 1, l + 2, \cdots, l + k - 1)\) 。
证明: \(A = \{l, l + 1, l + 2, \cdots, l + k - 1\}\) 中,由推论 1 有 \(\forall i,\ 1 \leq i \leq n\) , $ \exists x_i \in A, i \mid x_i$ ,于是 \(i \mid lcm(x_1, x_2, x_3, \cdots, x_m)\) 。
又 \(\bigcup_{i = 1}^{n} x_i \in A\) ,于是 \(lcm(x_1, x_2, x_3, \cdots, x_k) \mid lcm(l, l + 1, l + 2, \cdots, l + n + 1)\ s.t.\ 1 \leq i \leq k\) 。
于是 \(i \mid lcm(l, l + 1, l + 2, \cdots, l + n - 1)\ s.t.\ 1 \leq i \leq k\) ,于是 \(lcm(1, 2, 3, \cdots, n) \mid lcm(l, l + 1, l + 2, \cdots, l + k - 1)\) 。
\(\square\) 。
回到问题,若 \(\exists [l, r]\ s.t.\ l \geq 1\) ,有 \(\forall i \mid n\ s.t. l \leq i \leq r\) 。则有 \(lcm(l, l + 1, l + 2, \cdots, r) \mid n\) 。
由推论 2 有 \(lcm(1, 2, 3, \cdots, r - l + 1) \mid lcm(l, l + 1, l + 2, \cdots, r)\) ,于是 \(lcm(1, 2, 3, \cdots, r - l + 1) \mid n\) 。
于是 \(\forall j \mid n\ s.t.\ 1 \leq j \leq r - l + 1\) 。
于是问题简化为,可以让 \(x\) 从 \(1\) 开始线性向后寻找最大区间。
时间复杂度分析:最大的 \(x\) 满足 \(L = lcm(1, 2, 3, \cdots, x) \leq 10^{18}\) ,时间 \(T(x)\) ,不难发现 \(x\) 为常数,实际上复杂度为 \(O(1)\) 。
view
#include <bits/stdc++.h>
typedef long long ll;
void solve() {
ll n; std::cin >> n;
for (int x = 1; ; x++) if (n % x != 0) { std::cout << x - 1 << '\n'; return; }
}
signed main() {
int _ = 1; std::cin >> _;
while (_--) { solve(); }
return 0;
}