AtCoder Beginner Contest #148 题解

比赛链接
D.
给你n个数,问你最少取走多少个后剩下的n个能组成1~n的有序数列。

思路:
找原来n个数中最长的1~n的序列的长度,用n减去这个长度即可。

E.
给你一个n(0 <= n <= 1e18), 问你n * (n - 2) * (n - 4) * …的值是多少。
其中你可以认为n = 0和n = 1时的值都是1。现在问你乘积结尾有多少个0。

思路:
此题是求 !n 结尾有多少个0的翻版,还是要看5的倍数和偶数的乘积对结尾0的贡献。
当n为奇数时,显然结尾没有0。
当n为偶数时,只有10的倍数对结尾的0有贡献,不存在5,所以每次算出有多少个5的贡献,还要除以2。
至于为什么除以2:
5->0
10->1
15->1
20->2

也算是一道经典题目了, 别忘了开long long。

#include <bits/stdc++.h>

#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
 
using namespace std;
 
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
 
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }

i64 n;
 
int main() {
	ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("in", "r", stdin);
#endif
	
	cin >> n;
	if (n & 1) {
		cout << 0 << '\n';
		return 0;
	}
	i64 sum = 0;
	while (n /= 5) {
		sum += n / 2;
	}
	cout << sum << '\n';
		
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
	return 0;
}

F.
F题算是对我最有收获的一题了,我还出了一组hack数据,可以hack我自己的ac代码。数据如下:
6 1 3
1 2
2 3
2 4
4 5
5 6

正确输出应该是1,我的某一ac代码输出是3。我的水过ac代码

有n个点,有两个分别站在u,v两点,下面给出n-1条边(说明没有环,所有点都可以互相到达)。u的目标是尽可能的远离v(让他们俩相遇的时间变长),v的目标是尽可能的靠近u(让他们俩相遇的时间变短),u先手,v后手,每次u或v都不能不走,一定要走到与自己相邻的那个点。现在问你v走了多少步。

思路:
现在目标点(u要去的点),u到达目标点的时间肯定要比v严格小,等于不行(我的水过代码),至于为什么看hack数据就明白了,然后要找b到这个点的时间最长的那个点作为目标点,然后可以证明(画两种情况的例子)答案就是max(b到某个点的距离(目标点)) - 1。

#include <bits/stdc++.h>

#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
 
using namespace std;
 
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
 
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }

const int maxn = (int)1e5 + 1000;
int n, u, v, a[maxn], b[maxn], vis[maxn];
vvi g(maxn);
 
void dfs1(int now, int step) {
	for (auto it : g[now]) {
		if (a[it] == -1) {
			a[it] = step + 1;
			dfs1(it, step + 1);
		}
	}
}
void dfs2(int now, int step) {
	for (auto it : g[now]) {
		if (b[it] == -1) {
			b[it] = step + 1;
			dfs2(it, step + 1);
		}
	}
}

int main() {
	ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("in", "r", stdin);
#endif
	
	ms(a, -1); ms(b, -1);
	cin >> n >> u >> v;
	forn(i, n - 1) {
		int e1, e2;
		cin >> e1 >> e2;
		g[e1].pb(e2);
		g[e2].pb(e1);
	}
	a[u] = 0;
	dfs1(u, 0);
	b[v] = 0;
	dfs2(v, 0);
	int ans = -1;
	for1(i, n) {
		if (a[i] < b[i]) {
			ans = max(ans, b[i]);
		}
	}
	cout << (ans - 1) << '\n';
		
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
	return 0;
}

我看评论区的老哥发了一道cf上类似的题目也去做了一下,也正是因为这道题我才发现我之前的代码是水过的 -_-||。

相似的题目:题目链接
题目大意和上面基本一样,不一样的一点就是轮到每个人的那回合那个人可以选择不走,而不是像atcoder的那题一样一定要走到旁边的某个点,每个人走都是一回合,要求有多少回合数。所以答案就变成了max(b到某个点的距离(目标点)) * 2。如果像atcoder那题问的是v要走多少步,那就是max(b到某个点的距离(目标点))。

注意:一定要在u到达的时间严格小于v到达的时间的那些点里面选, 选v最晚到达的。

#include <bits/stdc++.h>
 
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, a, b) for (int i = (int)(a); i >= (int)b; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define ms(x, y) memset(x, y, sizeof(x))
 
using namespace std;
 
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;
typedef pair<i64, i64> pi64;
typedef double ld;
 
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }
 
const int maxn = 2 * (int)1e5 + 1000;
int n, x, a[maxn], b[maxn];
vvi g(maxn);
 
void dfs1(int now, int step) {
	for (auto it : g[now]) {
		if (a[it] == -1) {
			a[it] = step + 1;
			dfs1(it, step + 1);
		}
	}
}
void dfs2(int now, int step) {
	for (auto it : g[now]) {
		if (b[it] == -1) {
			b[it] = step + 1;
			dfs2(it, step + 1);
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.precision(10);
    cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("in", "r", stdin);
#endif
	
	ms(a, -1); ms(b, -1);
	cin >> n >> x;
	--x;
	forn(i, n - 1) {
		int e1, e2;
		cin >> e1 >> e2;
		--e1; --e2;
		g[e1].pb(e2);
		g[e2].pb(e1);
	}
	a[0] = 0;
	dfs1(0, 0);
	b[x] = 0;
	dfs2(x, 0);
	int p, max_num = -1;
	forn(i, n) {
		if (b[i] < a[i]) {
			max_num = max(max_num, a[i]);
		}
	}
	cout << max_num * 2 << '\n';
 
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
	return 0;
}

非常愉快的一次补题体验 : >

发布了51 篇原创文章 · 获赞 6 · 访问量 1659

猜你喜欢

转载自blog.csdn.net/qq_43555854/article/details/103659482
今日推荐