A.小红的 01 背包

能装多少装多少就行

$code:$

void solve() {
	int v, x, y;
	std::cin >> v >> x >> y;
	std::cout << v / x * y << '\n';
}

B.小红的 dfs

枚举每一行,然后对于第一行为 $dfs$ 的情况, 只存在第一列也为 $dfs$ 满足,其他行同理枚举一遍即可

void solve() {
	char g[3][3];
	for(int i = 0; i < 3; i ++)  {
		for(int j = 0; j < 3; j ++ ) {
			std::cin >> g[i][j];
		}
	}
	
	int ans = 9, v = 0;
	if(g[0][0] != 'd') v ++;
	if(g[0][1] != 'f') v ++;
	if(g[0][2] != 's') v ++;
	if(g[1][0] != 'f') v ++;
	if(g[2][0] != 's') v ++;

	ans = std::min(ans, v);

	v = 0;
	if(g[1][0] != 'd') v ++;
	if(g[1][1] != 'f') v ++;
	if(g[1][2] != 's') v ++;
	if(g[0][1] != 'd') v ++;
	if(g[2][1] != 's') v ++;

	ans = std::min(ans, v);

	v = 0;
	if(g[2][0] != 'd') v ++;
	if(g[2][1] != 'f') v ++;
	if(g[2][2] != 's') v ++;
	if(g[0][2] != 'd') v ++;
	if(g[1][2] != 'f') v ++;

	ans = std::min(ans, v);

	std::cout << ans << '\n';

}

C.小红的排列生成

先将其排序, 然后构造排列 $1, 2, 3, …, n$ , 统计代价即可

void solve() {
	int n;
	std::cin >> n;


	std::vector<int> a(n);
	for(int i = 0; i < n; i ++ ) {
		std::cin >> a[i];
	}

	std::sort(a.begin(), a.end());

	i64 s = 0;
	for(int i = 0; i < n; i ++ ) {
		s += std::abs(a[i] - i - 1);
	}

	std::cout << s << '\n';
}

D.小红的二进制树

由题意, 从一点往子节点走,要其形成的二进制数为奇数,即最后一位为1, 故统计子树中的一的个数即可

void solve() {
	int n;
	std::string s;
	std::cin >> n >> s;

	std::vector<int> w(n);
	for(int i = 0; i < n; i ++ ) {
		w[i] = s[i] - '0';
	}
	auto c = w;
	std::vector<std::vector<int>> adj(n);
	for(int i = 0; i < n - 1; i ++ ) {
		int u, v;
		std::cin >> u >> v;
		u --, v --;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	auto dfs = [&](auto self, int u, int fa) -> void {
		for(auto v : adj[u]) {
			if(v != fa) {
				self(self, v, u);
				w[u] += w[v];
			}
		}
	};

	dfs(dfs, 0, -1);

	for(int i = 0; i < n; i ++ ) {
		std::cout << w[i] - c[i] << '\n';
	}
	
}

E.小红的回文数

我们对每一个数的出现次数为奇数还是偶数进行状态统计, $0$ 表示为偶数, $1$ 表示为奇数, 总共有 $10$ 个数, 我们只需要用一个 $2^{10}$ 的数即可统计其状态, 然后能构造成回文串的话, 当且仅当只有一位为 $1$ 或者全为 $0$, 然后我们记录之前的状态, 然后我们从前往后统计, 选择当前位置 $i$, 然后枚举前面位置 $j$ , 只需要 $i$ 的状态与 $j$ 的状态相同或只有 $1$ 位有区别即可, 枚举肯定超时, 开一个桶记录即可, 然后计算贡献

void solve() {
	std::map<int, int> mp;
	mp[0] = 1;

	std::string s;
	std::cin >> s;

	i64 ans = 0, st = 0;
	for(int i = 0, n = s.size(); i < n; i ++ ) {
		int v = s[i] - '0';
		st ^= (1 << v);
		for(int j = 0; j < 10; j ++ ) {
			ans += mp[st ^ (1 << j)];
		}
		ans += mp[st];
		mp[st] ++;
	}

	std::cout << ans << '\n';

}

F.小红的矩阵修改

观察到 $n$ 非常的小, 每一位也就只有三种情况, 这很容易想到状压$dp$, 枚举每一位填什么即可, 复杂度也不高

void solve() {
	int n, m;
	std::cin >> n >> m;
	
	std::vector<std::vector<char>> g(n, std::vector<char>(m));
	for(int i = 0; i < n; i ++ ) {
		for(int j = 0;  j < m; j ++ ) {
			std::cin >> g[i][j];
			if(g[i][j] == 'r') g[i][j] = 0;
			if(g[i][j] == 'e') g[i][j] = 1;
			if(g[i][j] == 'd') g[i][j] = 2;
		}
	}
	
	auto check = [&](const std::vector<int> &o) -> bool {
		for(int i = 1; i < n; i ++ ) {
			if(o[i] == o[i - 1]) {
				return false;
			}
		}
		return true;
	}; 
	// 
	std::vector<std::vector<int>> st;
	// 
	for(int i = 0, r = pow(3, n); i < r; i ++ ) {
		int k = i;
		std::vector<int> v;
		while(k) {
			v.push_back(k % 3);
			k /= 3;
		}
		while(v.size() < n) v.push_back(0);
		std::reverse(v.begin(), v.end());
		if(check(v)) {
			st.push_back(v);
		}
	}

	auto get = [&](int pos, const std::vector<int> &a) -> int {
		int cnt = 0;
		for(int i = 0; i < n; i ++ ) {
			if(a[i] != g[i][pos]) {
				cnt ++;
			}
		}
		return cnt;
	};

	auto ok = [&](const std::vector<int> &a, const std::vector<int> &b) -> int {
		for(int i = 0; i < n; i ++ ) {
			if(a[i] == b[i]) {
				return false;
			}
		}
		return true;
	};
	// 3 ^ 4
	std::map<std::vector<int>, i64> dp, _dp;
	for(auto v : st) {
		dp[v] = get(0, v);
	}
	for(int i = 1; i < m; i ++ ) {
		_dp.clear();
		for(auto [x, y] : dp) {
			for(auto v : st) {
				int w = get(i, v);
				if(ok(x, v)) {
					if(!_dp.count(v)) {
						_dp[v] = y + w;
					} else {
						_dp[v] = std::min(_dp[v], y + w);
					}
				}
			}
		}
		dp = _dp;
	}
	
	i64 ans = 1e9;
	for(auto [x, y] : dp) {
		ans = std::min(ans, y);
	}
	std::cout << ans << '\n';

}