Atcoder Regular Contest 061 题解

ARC061C. Many Formulas *1089

首先预处理出原数区间 \([i,j]\) 所代表的真实数字。然后注意到 \(|s| \leq 10\),所以直接爆搜回溯最后判断即可。或者状压枚举也可以,反正非常简单。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
string s;
LL Sum[11][11], n, ans = 0;
bool vis[11];
void DFS(LL step)
{
	if(step == n)
	{
		LL last = 1;
		for(LL i = 1; i < n; i ++) 
		{
			if(!vis[i]) continue; 
			ans += Sum[last][i];
			last = i + 1;
		}
		ans += Sum[last][n];
		return;
	} 
	vis[step] = true;
	DFS(step + 1);
	vis[step] = false;
	DFS(step + 1);
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> s; n = s.length(); s = ' ' + s;
	for(LL i = 1; i <= n; i ++)
	{
		Sum[i][i] = (s[i] - '0');
		for(LL j = i + 1; j <= n; j ++) 
			Sum[i][j] = Sum[i][j - 1] * 10 + (s[j] - '0');
	}
	DFS(1);
	cout << ans << '\n';
	return 0;
} 

ARC061D. Snuke's Coloring *1682

注意到我们可以先不管 \(0\) 有多少个。最后可以容斥原理计算出一个染色格子都不包含的个数。注意到一个染色格子只会影响到相邻 \(9\)\(3\times 3\) 方格。我们枚举每个格子 \(i\),枚举这相邻的 \(9\)\(3\times 3\) 方格,然后计算对答案的贡献。

但是这样子会算重。我们考虑怎么重。显然,包含染色格子个数为 \(i\)\(3\times 3\) 方格的答案会是真实答案的 \(i\) 倍。因为里面的每个染色格子都会把它计算一遍。

然后最后容斥算出不包含染色个数的格子数量即可。形式化的说,就是 \((H-2)\times (W-2) - \sum ans_i\)。然后就做完了。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN = 100005;
LL H, W, n, ans[10], X[MAXN], Y[MAXN];
map<pair<LL, LL>, bool> mp;
void Solve(LL sx, LL sy, LL ex, LL ey)
{
	if(sx <= 0 || sy <= 0 || ex > H || ey > W) return;
	LL cnt = 0;
	for(LL i = sx; i <= ex; i ++)
		for(LL j = sy; j <= ey; j ++)
			if(mp.count(make_pair(i, j))) cnt ++;
	ans[cnt] ++;
	return;	
} 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> H >> W >> n;
	for(LL i = 1; i <= n; i ++)
	{
		cin >> X[i] >> Y[i];
		mp[make_pair(X[i], Y[i])] = true;
	}
	for(LL i = 1; i <= n; i ++)
	{
		Solve(X[i] - 2, Y[i] - 2, X[i], Y[i]);
		Solve(X[i] - 2, Y[i] - 1, X[i], Y[i] + 1);
		Solve(X[i] - 2, Y[i], X[i], Y[i] + 2);
		Solve(X[i] - 1, Y[i] - 2, X[i] + 1, Y[i]);
		Solve(X[i] - 1, Y[i] - 1, X[i] + 1, Y[i] + 1);
		Solve(X[i] - 1, Y[i], X[i] + 1, Y[i] + 2);
		Solve(X[i], Y[i] - 2, X[i] + 2, Y[i]);
		Solve(X[i], Y[i] - 1, X[i] + 2, Y[i] + 1);
		Solve(X[i], Y[i], X[i] + 2, Y[i] + 2);
	}
	for(LL i = 1; i <= 9; i ++) ans[i] /= i;
	ans[0] = (H - 2) * (W - 2);
	for(LL i = 1; i <= 9; i ++) ans[0] -= ans[i];
	for(LL i = 0; i <= 9; i ++) cout << ans[i] << '\n';
	return 0;
}

ARC061E. Snuke's Subway Trip *2502

不知道为什么洛谷评了绿,感觉题还挺有质量的。

考虑虚点建图。对于同一颜色连通块的点是可以免费互相到达的。所以我们可以考虑将它们连向一个虚点,进去的边权为 \(0\),出来的边权为 \(1\),因为切换连通块需要代价。这个可以过程用并查集维护。

然后我们发现我们建出了一个只含有 \(0/1\) 边权的图。我们要跑最短路。于是我们在新图上跑 \(0/1\) BFS,答案就是 \(dist_n\),然后我们就做完了。实现过程有点复杂。

#include <bits/stdc++.h>
using namespace std;
const int MAXM = 1000001;
int n, m, fa[MAXM], cnt, tmp[MAXM], Dist[MAXM];
bool vis[MAXM];
vector<pair<int, int> > E[MAXM];
struct Edge
{
	int v, w;
};
vector<Edge> Adj[MAXM];
int find(int x)
{
	if(fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}
void BFS01()
{
	vis[1] = true;
	deque<int> q;
	q.push_front(1);
	while(!q.empty())
	{
		int u = q.front();
		q.pop_front();
		for(int i = 0; i < (int)Adj[u].size(); i ++)
		{
			int v = Adj[u][i].v, w = Adj[u][i].w;
			if(vis[v]) continue;
			if(w == 0)
			{
				vis[v] = true;
				Dist[v] = Dist[u];
				q.push_front(v);
			}
			else
			{
				vis[v] = true;
				Dist[v] = Dist[u] + 1;
				q.push_back(v);
			}
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> m; cnt = n;
	for(int i = 1; i <= m; i ++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		E[w].push_back(make_pair(u, v));
	}
	for(int i = 1; i < MAXM; i ++)
	{
		set<int> s;
		for(int j = 0; j < (int)E[i].size(); j ++) 
		{
			s.insert(E[i][j].first);
			s.insert(E[i][j].second);
		}
		for(auto kv : s) fa[kv] = kv;
		for(int j = 0; j < (int)E[i].size(); j ++)
		{
			int fu = find(E[i][j].first), fv = find(E[i][j].second);
			fa[fu] = fv;
		}
		for(auto kv : s) if(find(kv) == kv) tmp[kv] = ++ cnt;
		for(auto kv : s) 
		{
			Adj[kv].push_back(Edge{tmp[find(kv)], 0});
			Adj[tmp[find(kv)]].push_back(Edge{kv, 1});
		}
	}
	BFS01();
	if(vis[n]) cout << Dist[n] << '\n';
	else cout << -1 << '\n';
	return 0;
}

这场 F 也是巨大不可做题,不补了。

posted @ 2024-11-22 10:13  DataEraserQ  阅读(11)  评论(0)    收藏  举报