--- tags: APIO --- # APIO 2019-A 奇妙な装置 (Strange Device) OI に $O(1)$ 数学問を出すのをやめなさーい! ( $O(1)$ ではない) ???「Aは問題としてreject」「情報オリンピックの問題として失格」「IOIで出たら会場爆破します」 ## 問題文 https://apio2019.ru/upload/statements/Japanese.pdf https://oj.uz/problem/view/APIO19_strange_device 2つの数字の組を表示する装置があり、 時刻 $t$ のとき、 $((t + \lfloor\frac{t}{B}\rfloor)\ \%\ A,\ t\ \%\ B)$ を表示します。 装置の電源は $[l_1, r_1],\ [l_2, r_2],\ \dots,\ [l_n, r_n]$ の間点いていました。 この間に表示された数字の組としてありえるものの個数はいくつでしょうか? ## 考察 $t\ \%\ B$ のほうがシンプルなので、$t$ を $B$ 周期でひとまとめにすると、 $(t + \lfloor\frac{t}{B}\rfloor)\ \%\ A$ は $B + 1$ ずつずれていくことになる。 よって、全体の周期は $\frac{AB}{\gcd(A, B + 1)}$ になって、各区間を $\frac{AB}{\gcd(A, B + 1)}$ で余りをとって数えれば良い。 0-indexed に注意。 $(t + \lfloor\frac{t}{B}\rfloor)\ \%\ A$ って不自然すぎて何の面白みもない… ## 実装 https://oj.uz/submission/210207 ```cpp #include <bits/stdc++.h> using namespace std; using ull = unsigned long long; #define rep(n) for(int i=0;i<n;++i) #define all(i) begin(i),end(i) #define Sort(a) sort(all(a)) #define Rev(a) reverse(all(a)) using u128 = __uint128_t; signed main(){ cin.tie(nullptr); ios::sync_with_stdio(false); ull n, a, b; cin >> n >> a >> b; u128 mod = a / gcd(a, b + 1) * u128(b); vector<pair<ull, int>> query; rep(n){ ull l, r; cin >> l >> r; if(r - l + 1 >= mod){ cout << ull(mod) << endl; return 0; } l %= mod; r %= mod; r++; query.emplace_back(l, 1); query.emplace_back(r, -1); if(l > r){ query.emplace_back(mod, -1); query.emplace_back(0, 1); } } Sort(query); Rev(query); ull at = 0, cnt = 0, ans = 0; while(query.size()){ ull next = query.back().first; if(cnt) ans += next - at; at = next; while(query.size() && query.back().first == at){ cnt += query.back().second; query.pop_back(); } } cout << ans << endl; } ```