* 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;
}
posted @ 2023-09-05 21:18  zsxuan  阅读(6)  评论(0编辑  收藏  举报