1、Codeforces 463D Gargari and Permutations
参考:http://blog.csdn.net/qq_24451605/article/details/48630899
题意:
给出 k 个序列,每个序列都由 1...n 组成,求这 k 个序列的最长公共子序列的长度
解题思路:
dp[i] 表示以 i 结尾的最长公共子序列的长度
cnt[i] 表示 i 出现过的次数,当 cnt[i] 等于 k 的时候判断是否进行转移
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e3 + 10;
int n, k;
int num[maxn][maxn], pos[maxn][maxn], cnt[maxn], dp[maxn];
vector<int> V;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d %d", &n, &k);
for (int i = 1; i <= k; ++i) {
for (int j = 1; j <= n; ++j) {
scanf("%d", &num[i][j]);
pos[i][num[i][j]] = j;
}
}
memset(dp, 0, sizeof(dp));
memset(cnt, 0, sizeof(cnt));
V.push_back(0);
for (int i = 1; i <= k; ++i) {
for (int j = 1; j <= n; ++j) {
++cnt[num[i][j]];
if (cnt[num[i][j]] == k) {
for (int t = 0; t < (int)V.size(); ++t) {
bool flag = true;
for (int v = 1; v <= k; ++v) {
if (pos[v][V[t]] > pos[v][num[i][j]]) {
flag = false;
break;
}
}
if (flag) {
dp[num[i][j]] = max(dp[num[i][j]], dp[V[t]]+1);
}
}
V.push_back(num[i][j]);
}
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
return 0;
}
2、Codeforces 666A Reberland Linguistics
参考:http://www.cnblogs.com/qhy285571052/p/d51cf80b94c4caf676fa33aef57096e0.html
http://www.voidcn.com/blog/wlx65003/article/p-6046070.html
题意:
一个字符串由长度大于 4 的根和长度为 2 或 3 的若干个后缀组成,两个相邻的后缀不能一样,问有多少种后缀,并按字典序输出
解题思路:
dp[i] 表示第 i 个位置到字符串结束能否划分成合法后缀
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e4 + 10;
string s;
set<string> Set;
int dp[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
cin >> s;
s = s.substr(5);
int len = s.length();
string t;
dp[len] = 1;
for (int i = len-1; i >= 0; --i) {
for (int j = 2; j <= 3; ++j) {
t = s.substr(i, j);
if (((int)s.find(t, i+j) != i+j || dp[i+5]) && dp[i+j]) {
Set.insert(t);
dp[i] = 1;
}
}
}
printf("%d\n", Set.size());
for (set<string>::iterator itr = Set.begin(); itr != Set.end(); ++itr) {
cout << *itr << endl;
}
return 0;
}
3、Codeforces 269B Greenhouse Effect
参考:http://blog.csdn.net/qq_24451605/article/details/48649147
http://www.cnblogs.com/hundundm/archive/2013/02/03/2891217.html
题意:
有 n 颗植物,种类为 m 种,种在一个无限长的实数轴上
现在可以通过改变一些植物的坐标,使得最后所有植物的种类沿 x 轴正方向为不下降序列
问最少要改变多少植物的位置
解题思路:
植物的坐标是没什么用的,因为一定是严格递增的
dp[i] 代表前 i 个植物,要保证升序的情况下最多保留的植物的个数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ll mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 5e3 + 10;
int n, m;
int s[maxn], dp[maxn];
double x;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%d %lf", &s[i], &x);
}
s[++n] = m + 1;
for (int i = 1; i <= n; ++i) {
dp[i] = 0;
for (int j = 1; j < i; ++j) {
if (s[i] >= s[j]) {
dp[i] = max(dp[i], dp[j]);
}
}
++dp[i];
}
printf("%d\n", n-dp[n]);
return 0;
}
4、Codeforces 375B Maximum Submatrix 2
参考:http://blog.csdn.net/qq_24451605/article/details/48651451
题意:
给出一个 01 矩阵,行与行之间可以互换位置,问能够得到最大的全 1 矩阵的面积
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ll mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 5e3 + 10;
int n, m, ans = 0;
char num[maxn][maxn];
int dp[maxn][maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%s", num[i]+1);
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (num[i][j] == '1') {
dp[j][i] = dp[j-1][i] + 1;
}
}
}
for (int j = 1; j <= m; ++j) {
sort(dp[j] + 1, dp[j] + 1 + n);
for (int i = n; i >= 1; --i) {
ans = max(ans, dp[j][i] * (n - i + 1));
}
}
printf("%d\n", ans);
return 0;
}
5、Codeforces 577B Modulo Sum
参考:http://codeforces.com/contest/577/standings
解题思路:
用 sum[i] 表示前缀和,当 n > m 时,根据鸽巢原理,sum[i] % m 的值必然会出现相等的情况,假如相等的为 sum[low] % mod 和 sum[high] % mod,那么区间 (low, high] 的和必然是 m 的倍数
当 n ≤ m,用 dp[i][j] 表示区间 [l, i] 是否存在某些数的和对 m 取模为 j,dp[i][j] = 1 表示存在
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ll mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e3 + 10;
int n, m;
int a[1000010], dp[maxn][maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
if (n > m) {
printf("YES\n");
} else {
for (int i = 1; i <= n; ++i) {
dp[i][a[i] % m] = 1;
for (int j = 0; j <= m-1; ++j) {
dp[i][(j + (a[i] % m)) % m] |= dp[i-1][j];
dp[i][j] |= dp[i-1][j];
}
}
if (dp[n][0]) {
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}