版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ https://blog.csdn.net/corsica6/article/details/88835697
C.Sequence Growing Easy
*D.Isomorphism Freak
同色的条件:找到 路径上的中点(一条边/一个点),中点的所有子树同构的,且染色种类数为 ,所以找到树的直径 ,第一问答案即 。
- 若 为奇数,重心为一条边 ,将 作为第一层,每层填满,第二问的代价是唯一的。
- 否则 为偶数,重心为一个点 ,可以将 作为第一层求出代价,也可以将任意与 相连的点 和 一起构成第一层求出代价(使得直径加一,但第一问答案不变),所有情况取 即可。
E.Sequence Growing Hard
如果新增的位置值与原来这个位置的值相等,那么可以认为填的是后面一个位置而不是这个位置。
所以假设填的数是
,要么填在末位,要么它后一个位置的数严格
。
在序列末端添一个 ,每次在一个位置填数并向它后一个位置连边,那么这就是一个树,满足以下条件:
- 设 分别表示点 的添加时间和值。
- 互不相同,
设
表示
个点,
的方案数,枚举
最小的儿子转移:
前缀和优化后复杂度
*F.Simple Subsequence Problem
构造序列自动机,如:
110[00011001]可以转移到1100[0011001],1101[1001]
其中
表示已经选了
,要在
中选一个子序列拼上。
构图得到
,直接DP(逐次求出长度为
的子序列的方案数,每次只向后转移一步0/1),复杂度
。
code from wxh010910
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 1048580;
const int M = 25;
int n, m, len, ans, f[M][N], g[M][N];
char s[N];
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m);
for (int i = 0; i <= n; ++i) {
scanf("%s", s);
for (int j = 0; j < 1 << i; ++j) {
if (s[j] == '1') {
f[i][j] = 1;
}
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < 1 << i; ++j) {
int b = j >> (i - 1) & 1, r = 0;
for (; r < i && (j >> i - r - 1 & 1) == b; ++r);
g[i][j] = r == i ? -1 : r;
}
}
for (int i = 0; i <= n; ++i) {
for (int j = 1; i + j <= n; ++j) {
for (int k = 0; k < 1 << i + j; ++k) {
f[i][k >> j] += f[i + j][k];
int t = g[j][k & (1 << j) - 1];
if (~t) {
f[i + j - t][(k >> j << j - t) | (k & (1 << j - t) - 1)] += f[i + j][k];
}
}
}
for (int j = (1 << i) - 1; ~j; --j) {
if (f[i][j] >= m) {
len = i, ans = j;
}
}
}
for (int i = len - 1; ~i; --i) {
putchar((ans >> i & 1) + '0');
}
putchar(10);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}