补题链接:Here
A - Payment
水题,请问在使用 元钞票的倍数的钱付款以后能找零多少
void solve() {int n; cin >> n, n %= 1000;cout << (n == 0 ? 0 : 1000 - n);}
B - Judge Status Summary
利用 map 的键值特性存值
void solve() {int n; cin >> n;string s;map<string, int>mp;while (n--) {cin >> s;mp[s]++;}cout << "AC x " << mp["AC"] << "\n";cout << "WA x " << mp["WA"] << "\n";cout << "TLE x " << mp["TLE"] << "\n";cout << "RE x " << mp["RE"] << "\n";}
C - H and V
题意:给一个n x m的矩阵,由’#‘和’.’构成,分别代表黑色和白色,现在你可以任选若干行和若干列将其涂成红色,问有多少种涂法使最终只有k个黑色。
因为n和m都是小于等于6的,所以对于一个 的矩阵所有情况也就
种,那就直接爆搜。
爆搜
string g[10];int ans, cnt;int h, w, k;bool vis[10];void dfs(int r, int c, int sum) {if (r == h and c == w) {if (cnt - sum == k)ans++;return ;}int num = 0;if (r == h) {for (int i = 0; i < h; ++i)if (g[i][c] == '#' and (!vis[i]))num++;dfs(r, c + 1, sum + num);dfs(r, c + 1, sum);} else {for (int i = 0; i < w; ++i)if (g[r][i] == '#')num++;vis[r] = 1;dfs(r + 1, c, sum + num);vis[r] = 0;dfs(r + 1, c, sum);}}void solve() {cin >> h >> w >> k;for (int i = 0; i < h; ++i)cin >> g[i];for (int i = 0; i < h; ++i)for (int j = 0; j < w; ++j)if (g[i][j] == '#')cnt++;dfs(0, 0, 0);cout << ans << "\n";}
二进制枚举
string s[10];void solve() {int h, w, k;cin >> h >> w >> k;for (int i = 0; i < h; ++i)cin >> s[i];int ans = 0;for (int i = 0; i < (1 << h); ++i)for (int j = 0; j < (1 << w); ++j) {int cnt = 0;for (int ii = 0; ii < h; ++ii)for (int jj = 0; jj < w; ++jj)if ((i >> ii & 1) && !(j >> jj & 1))cnt += s[ii][jj] == '#';ans += cnt == k;}cout << ans << "\n";}
3道类似的题目
AtCoder Beginner Contest 167 C Skill Up 满足C(n,1),C(n,2),C(n,3),……,C(n,n)的深搜dfs
AtCoder Beginner Contest 165 C Many Requirements 深搜dfs+生成非递减数组
AtCoder Beginner Contest 159 E Dividing Chocolate 二维前缀和+子矩阵和+深搜行+枚举列+注意行边界处理+注意列边界处理
D - Chat in a Circle
现在有一排数字,现在要将这排数字按顺序放入一个圈,每个数字在插入圈时,他的权值就是相邻两个数字中小的那个,第一个插入的人权值为0,问总权值是多少。
既然要让权值最大,那必然要让大的值先插入,否则会被相邻的小的值影响,导致不能贡献权值。以为是一个圈,左右两边都能贡献权值,所以除了最大的数只能贡献一次,剩余的数都可以贡献两次。
using ll = long long;bool cmp(ll a, ll b) {return a > b;}void solve() {int n; cin >> n;ll sum = 0;int a[n + 1];for (int i = 1; i <= n; ++i)cin >> a[i];sort(a + 1, a + 1 + n, cmp);sum += a[1];int idx = 2;for (int i = 2; i < n; ++i) {if (i % 2 == 0)sum += a[idx]; // 贡献两次else sum += a[idx++];}cout << sum;}
F - Intervals on Tree
题意:给你一棵树,节点为1到n,取若干连续编号的节点,求出其连通分量,问所有连续段的连通分量之和。
因为是树,所以一条边必然连接两个连通分量,所以我们可以假设把每个点看成一个连通分量,然后每加入一个边,就把含他的 的数量去掉。
void solve() {int n; cin >> n;ll sum = 0;int l, r;for (int i = 1; i <= n; ++i)sum += 1ll * i * (n - i + 1);for (int i = 1; i < n; ++i) {cin >> l >> r;if (l > r)swap(l, r);sum -= 1ll * l * (n - r + 1);}cout << sum;}
