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;
}

非常愉快的一次補題體驗 : >

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章