题目大意:有一个播放器用于播放音乐,现在给出s(已有曲目的数量),n给出记录的长度。播放器有随机播放的功能,每次生成一个1~s的随机系列进行播放,当s首歌全部播放完后,重新生成一个播放序列。现在有一段长度为n的播放记录片段(即不完全,前后可能还有歌曲),问说该片段的第一首歌可能处于某个播放序列的哪个位置,输出位置的可能数。
解题思路:首先维护一个长度为n的区间,遍历一遍播放序列,判断每个位置往后s个是否有相同的歌曲,如果有则说明不能作为某个播放序列的开头。然后枚举记录片段第一首歌可能存在的位置进行判断,检查后面每s个位置是否能作为开头即可。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 1e5+5; int s, n, p[N], c[N]; bool flag[N]; void init () { scanf("%d%d", &s, &n); int tmp = 0; memset(flag, 0, sizeof(flag)); memset(c, 0, sizeof(c)); for (int i = 0; i < n; i++) { scanf("%d", &p[i]); if (i < s) { if (c[p[i]]) tmp++; c[p[i]]++; } } for (int i = 0; i < n; i++) { if (tmp == 0) flag[i] = true; if (c[p[i]] == 2) tmp--; c[p[i]]--; int k = i + s; if (k >= n) continue; if (c[p[k]]) tmp++; c[p[k]]++; } } bool judge (int x) { for (int i = x; i < n; i += s) if (!flag[i]) return false; return true; } int solve () { memset(c, 0, sizeof(c)); int ans = 0; for (int i = 0; i < s; i++) { if (judge(i)) ans++; if (i >= n) continue; if (c[p[i]]) break; c[p[i]]++; } return ans; } int main () { int cas; scanf("%d", &cas); while (cas--) { init(); printf("%d\n", solve()); } return 0; }
原文:http://blog.csdn.net/keshuai19940722/article/details/19292045