//144K 141MS C++
#include <cstdio>
#include <cstring>
using namespace std;
int K;
int N;
const int MAX = 10001;
char flag[MAX];
int completeCollectionNum = 0;
int main() {
while(scanf("%d %d", &N, &K) != EOF) {
memset(flag, 0, sizeof(flag));
int unAppearNum = K;
for (int i = 1; i <= N; i++) {
int val;
scanf("%d", &val);
if (flag[val]) {
} else {
flag[val] = 1;
unAppearNum--;
if (unAppearNum == 0) {
completeCollectionNum++;
memset(flag, 0, sizeof(flag));
unAppearNum = K;
}
}
}
printf("%d\n", completeCollectionNum+1);
}
}
一道考智力的题,不适合我这样的庸才,直接看了后面的discuss:
证明子序列长度为至少是n当且仅当序列是这样的()()...()[],一个()是一次1..m都出现的序列,共n个。 必要性。数学归纳法。n>=1是,序列显然是()[],假设n>=k是,序列是k个()+[],如果n>=k+1,取第k个()的最后一个素,这个元素在长度为k的某个子序列中一定会用到,如果用不到就把它放到[]中去,这样做第k个()仍然是一次1..m都出现的序列,再取前一个元素,由归纳假设保证第k个()中一定有一个元素满足要求,由于n>=k+1,所以在这个元素之后必然会出现1..m的所有元素一次,所以[]=()[]' 充分性。太显然了,没什么证的。
假设有排序的个数为n,则其最短的非子序长度,可由下面方法求得。 如果存在其有包括全排序的一个最小组合,(1,2,...n),(次序不限,只要有1...n的数字就行了,也有可能有重复数字) 找到其所有这样组合。可合成()()()...()[],( 设有k个括号,[]里的元素可能为空) 则其最短的非子序长度为k+1; 原因: 长度为k的子序,都可由前k个括号里抽出一个数组成。 但对于k+1,就找不到一个组合,因为最后一个组合里少了需要的最后一个数。 如本例子中: 14 5 1 5 3 2 5 1 3 4 4 2 5 1 2 3 首先有(1,5,3,2,5,1,3,4)(4,2,5,1,2,3)[] 故其最短非子序长度为3;
// | ... a1| | ... a2| ... | ac|| ... | // 后面的| ... | 是没有完整的 1 - k // 统计前面出现完整的 1 - k 的个数 c , c + 1 就是答案 // 设每一个完整的1 - k 以 ai结束( 1 <= i <= c ) // 假设最后一个缺少 aj , 则无法构造 a1 a2 ... ac aj