Thinking about it:
我的思路跟sliding window有点类似。假设已经确定了一个区间[l, r],序列中从 l 到 r 恰好包含了[1, K]的各个元素,则从 r 开始继续迭代序列的各个位置,如果发现了1到K的数,则做以下处理:
如果 这个数 刚好是 l 位置上的数,那么就意味着这个区间可能缩短,则同时更新 l 和 r,计算区间长度的变化。
如果 这个数 不是 l 上的数,那么即使 更新了 r 那也不能使答案更好,所以可以不做处理。
那么第一个符合条件的[l, r]可以直接迭代得出,如果迭代一次都不能发现[1, K]的各个数,那么这个序列肯定是不能满足的要求。
PS:
虽然AC了这题,但是感觉对这道题的题解表述上还有些欠缺。
Code:
/** * AC @ Sep 11th 2015 * Run Time : 0.739s */ #include <bits/stdc++.h> using namespace std; const int MAXN = 1000 + 50; int var[MAXN*1000]; int Case = 0; int N, M, K; void init() { for (int i = 1; i <= 3; ++i) { var[i] = i; } int sum = 6; for (int i = 4; i <=N ; ++i) { var[i] = sum % M + 1; sum -= var[i-3]; sum += var[i]; } } void done() { int pos[MAXN] = {0}; int counter = 0; for (int i = 1; i <= N && counter < K; ++i) { if (var[i] >= 1 && var[i] <= K && !pos[var[i]]) { ++ counter; } pos[var[i]] = max(pos[var[i]], i); } if (counter < K) { cout << "Case " << (++Case) << ": sequence nai" << endl; return ; } int minPos = MAXN * 1000, maxPos = -1; for (int i = 1; i <= K; ++i) { minPos = min(minPos, pos[i]); maxPos = max(maxPos, pos[i]); } int ans = maxPos - minPos + 1; for (int i = 1; i <= N; ++i) { if (var[i] >= 1 && var[i] <= K) { if (pos[var[i]] == minPos || pos[var[i]] == maxPos || i > maxPos) { pos[var[i]] = i; minPos = MAXN * 1000, maxPos = -1; for (int j = 1; j <= K; ++j) { minPos = min(minPos, pos[j]); maxPos = max(maxPos, pos[j]); } ans = min(ans, maxPos - minPos + 1); } } } cout << "Case " << (++Case) << ": " << ans << endl; } void work() { cin >> N >> M >> K; init(); done(); } int main(int argc, char const *argv[]) { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while (T --) { work(); } return 0; }