SMU Autumn 2023 Round 5

发布时间 2023-09-26 20:24:31作者: Ke_scholar

SMU Autumn 2023 Round 5

A. Everyone Loves to Sleep

把时间都转成分钟,然后存起来,二分找到离他睡觉点最近的一个时间段,减去他的睡觉点,如果最近的在第二天,则把中间的这段时间加起来

#include <bits/stdc++.h>
#define int long long
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;

void solve() {

	int n, H, M;
	cin >> n >> H >> M;
	int HM = H * 60 + M;

	set<int> s;
	s.insert(INT_MAX);
	for (int i = 0; i < n; i ++) {
		int n, m;
		cin >> n >> m;
		s.insert(n * 60 + m);
	}

	auto t = s.lower_bound(HM);
	int ans ;
	if (*t == INT_MAX) {
		t = s.begin();
		ans = 24 * 60 - HM + *t;
	} else
		ans = *t - HM;
	cout << ans / 60 << ' ' << ans % 60 << '\n';
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int T;
	cin >> T;
	while (T--) {
		solve();
	}

	return 0;
}

B. Minimum Varied Number

倒着搜一遍即可,正着搜会超时,也可以直接打表

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		bitset<10> v;
		vector<int> ans;
		bool ok = false;		
		auto dfs = [&](auto self, int sum) {
			if(ok) return;
			if (sum == n) {
				ok = true;
				reverse(ans.begin(), ans.end());
				for (auto i : ans)
					cout << i ;
				cout << '\n';
				return ;
			}
			for (int i = 9; i >= 1; i --)
				if (!v[i]) {
					v[i] = 1;
					ans.push_back(i);
					self(self, sum + i);
					v[i] = 0;
					ans.pop_back();
				}
		};

		dfs(dfs, 0);

	}

	return 0;
}

D. Add Modulo 10

对于以\(1,3,7,9\)结尾的经过几次运算最后都会变成\(2,4,8,6\)的循环,而对于\(5,0\)结尾的,最后都会变成\(0\)结尾,所以我们可以先把不是以\(2\)结尾的都经过几次运算直到以\(2\)结尾,然后去模上\(20(2+4+8+6)\),就能把这些数都转换到\(20\)以内,然后就是比较一下就好了

#include <bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;
using i64 = long long;

typedef pair<i64, i64> PII;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int T;
	cin >> T;
	while(T--){
		int n;
		cin >> n;
		vector<i64> a(n);
		for(auto &i : a) cin >> i;
		
		bool f = true;
		for(auto &i : a){
			while(i % 10 != 2 && i % 10 != 0)
				i += i % 10;
			if(i % 10 == 2)
				i %= 20;			
		}

		for(int i = 0;i + 1 < n;i ++)
			if(a[i] != a[i + 1])
				f = false;

		cout << (f ? "Yes" : "No") << '\n';
	}

	return 0;
}

G. Make Them Equal(dp)

假设将\(a_i\)变成\(b_i\)需要\(f_i\)个操作数,你现在能操作\(k\)步,每个\(f_i\)操作可以使你获得\(c_i\)个硬币,问现在怎样使你得到的硬币数最大?

是不是很熟悉?

假如我将问题转换成:你现在有\(V\)体积的背包,你可以装\(n\)个物品,每个物品体积为\(v_i\),价值为\(c_i\),问你现在能装的最大价值是多少?

没错,就是很典型的背包题,只要我们预处理出\(f_i\),那么这个题也就迎刃而解了!

如果你没有判断$k \geq \sum\limits_{i=1}^{n}f_i $这一步的话,那么你就不能开#define int long long.

#include <bits/stdc++.h>
#define int long long
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;

vector<int> f(2048, INT_MAX);

void solve() {
	int n, k;
	cin >> n >> k;
	vector<int> b(n), c(n);
	int sum = 0, ans = 0;
	for (auto &i : b) {		
		cin >> i;
		sum += f[i];
	}
	for (auto &i : c) {
		cin >> i;
		ans += i;
	}

	if(k >= sum){
		cout << ans << '\n';
		return ;
	}

	vector<int> dp(k + 1);
	for (int i = 0; i < n; i ++)
		for (int j = k; j >= f[b[i]]; j--)
			dp[j] = max(dp[j - f[b[i]]] + c[i], dp[j]);

	cout << dp[k] << '\n';
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	f[1] = 0;
	for (int i = 1; i <= 1000; i ++)
		for (int j = 1; j <= i; j ++)
			f[i + i / j] = min(f[i + i / j], f[i] + 1);

	int T;
	cin >> T;
	while (T--) {
		solve();
	}

	return 0;
}

I. Div. 7

如果能整除直接就输出,否则就去枚举它的个位

#include <bits/stdc++.h>
#define int long long
#define debug(a) cout<<#a<<"="<<a<<'\n';

using namespace std;

void solve() {
	int n;
	cin >> n;
	if(n % 7 == 0){
		cout << n << '\n';
	}else{
		for(int i = 0;i <= 9;i ++){
			if((n / 10 * 10 + i) % 7 == 0){
				cout << (n / 10 * 10 + i) << '\n';
				return ;
			}
		}
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int T;
	cin >> T;
	while (T--) {
		solve();
	}

	return 0;
}