C. 调手表
题目描述:
一块表,只有小时和分钟, $ n $ 为进制。每次只能够 $ +1 $ 或 $ +k $ ,从任意一个分钟调到另外任意一个分钟最少需要按多少次。
数据范围:
$ 0\lt k \lt n \le 10^5 $
题解:
因为所有的起点都是等价的,所以只需要求出从 $ 0 $ 开始到其他各个时间的就行。
使用 $ BFS $ 搜索,每个点有两种情况, $ +1 $ 或 $ +k $ ,第一次访问到的时候就是最短次数。取最大值就行。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| using namespace std; using namespace FAST_IO; const ll mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const ll INF_LL = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-5; const int maxn = 1e5 + 10; const int maxm = 1e5 + 10; int t, n, m, k; queue<int> q; int cnt[maxn]; int ans = 0; void bfs() { q.push(0); cnt[0] = 0; while (!q.empty()) { auto out = q.front(); q.pop(); int v = (out + 1) % n; if (!(v == out || cnt[v] != 0 || v == 0)) { cnt[v] = cnt[out] + 1; ans = max(ans, cnt[v]); q.push(v); }
v = (out + k) % n; if (!(v == out || cnt[v] != 0 || v == 0)) { cnt[v] = cnt[out] + 1; q.push(v); ans = max(ans, cnt[v]); } } } int main() {
#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif read(n, k); bfs(); cout << ans << endl;
return 0; }
|