A. Sereja and Algorithm
水题不解释。
B. Sereja ans Anagrams
模p同余的为一组,随便搞。
C. Sereja and the Arrangement of Numbers
我还以为是找规律。。。
把每个数当成一个点。就有一个图。让后求欧拉路什么的。
D. Sereja and Sets
这个思路感觉很巧妙(可能是我太弱了),我们对于每一段连续的d,找到不包含它们的所有集合,这些集合的子集一定不可行。
见代码。
/*
* Problem: D. Sereja and Sets
* Author: Shun Yao
*/ #include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h> #include <map>
#include <set>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#include <bitset>
#include <utility>
#include <iomanip>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional> //using namespace std; int n, m, d, bad[1 << 21], s[100010], cnt[25]; int main(/*int argc, char **argv*/) {
int i, j, k, l, tmp, ans; scanf("%d%d%d", &n, &m, &d);
for (i = 0; i < m; ++i) {
scanf("%d", &j);
for (k = 0; k < j; ++k) {
scanf("%d", &l);
s[l - 1] = i;
}
}
memset(bad, 0, sizeof bad);
for (i = 0; i < n; ++i) {
if (i >= d)
--cnt[s[i - d]];
++cnt[s[i]];
if (i >= d - 1) {
tmp = 0;
for (j = 0; j < m; ++j)
if (!cnt[j])
tmp += 1 << j;
bad[tmp] = 1;
}
}
ans = 21;
for (i = (1 << m) - 1; i >= 0; --i) {
if (!bad[i]) {
k = i;
l = 0;
while (k) {
++l;
k -= k & -k;
}
ans = std::min(ans, l);
} else {
k = i;
while (k) {
l = k & -k;
bad[i - l] = 1;
k -= l;
}
}
}
printf("%d", ans); fclose(stdin);
fclose(stdout);
return 0;
}
E. Sereja and Intervals
问题是求n个互不包含的区间且其中一个区间的左端是x的方案数。(原题n个区间排列也算不同方案,为了方便思考我们可以考虑排列算相同方案,然后让结果成以n的阶乘。
f[i][j][k]代表目前到i,有左端点j个,右端点k个的合法方案数。(好像还有其他的状态定义,也可以做)