AtCoder Beginner Contest 281 A-F 题解

比赛链接

A - Count Down

先这样,就这样。

点击查看代码
#include<cstdio>
int n;
int main() {
	scanf("%d", &n);
	for(int i = n; i >= 0; i--) printf("%d\n", i);
	return 0;
}

B - Sandwich Number

好好读题

赛时想复杂了,其实就直接判断两边字母和中间数字就好,注意中间数字是否存在前导零!

点击查看代码
#include<cstdio>
#include<cstring>
int n, tot;
char s[20];

bool check(int l) {
	for(int i = l; i < l + 6; i ++) {
		if(s[i] > '9' || s[i] < '0' || (i == l && s[i] == '0')) return 0;
	}
	return 1;
}
int main() {
	scanf("%s", s + 1);
	n = strlen(s + 1);
	if(n != 8 || !check(2)) {
		puts("No");
		return 0;
	}
	if(s[1] > 'Z' || s[1] < 'A' || s[8] > 'Z' || s[8] < 'A') {
		puts("No");
		return 0;
	}
	puts("Yes");
	return 0;
}

C - Circular Playlist

前缀和,取模,然后枚举时间段判断。

点击查看代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
const int N = 1e5 + 5;
int n, t, a[N];

signed main() {
	scanf("%lld %lld", &n, &t);
	for(int i = 1; i <= n; i ++) {
		scanf("%lld", &a[i]);
		a[i] += a[i - 1];
	}
	t %= a[n];
	for(int i = 0; i < n; i ++) {
		if(t >= a[i] && t < a[i + 1]) {
			printf("%lld %lld\n", i + 1, t - a[i]);
			return 0;
		}
	}
	return 0;
}

D - Max Multiple

观察数据范围,发现 n,d,k 都不大,

因此可以直接定义状态 dp[i][j][k] 表示 前 i 位中选了 j 位,所选数的和 取模 d 余 k 时能达到的 d 的最大倍数。

然后直接枚举这三维的状态,转移方程即可。

点击查看代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
const int N = 105;
int n, d, K, a[N], dp[N][N][N];

int get_num(int x, int y) {
	return ((x - y) % d + d) % d; 
}

signed main() {
	
	scanf("%lld %lld %lld", &n, &K, &d);
	
	for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]);
	memset(dp, -1, sizeof(dp));
	for(int i = 0; i <= n; i ++) dp[i][0][0] = 0;
	for(int i = 1; i <= n; i ++) {
		for(int j = 1; j <= i; j ++) {
			for(int k = 0; k < d; k ++) {
				int tmp = get_num(k, a[i]);
				dp[i][j][k] = dp[i - 1][j][k];
				if(dp[i - 1][j - 1][tmp] != -1) dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][tmp] + (tmp + a[i]) / d * d);
			}
		}
	}
	printf("%lld", dp[n][K][0]);
	
	return 0;
}

E - Least Elements

直接用 vector 模拟平衡树修改查询……

点击查看代码
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long
const int N = 2e5 + 5;
int n, m, k, a[N], ans;

vector<int> v;

signed main() {
	scanf("%d %d %d", &n, &m, &k);
	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	for(int i = 1; i <= m; i ++) v.push_back(a[i]);
	sort(v.begin(), v.end());
	
	for(int i = 0; i < k; i ++) ans += v[i];
	printf("%lld ", ans);
	int x;
	for(int i = 2; i <= n - m + 1; i ++) {
		bool tag = 0;
		auto pos = lower_bound(v.begin(), v.end(), a[i - 1]);
		if((pos - v.begin()) < k) ans -= a[i - 1], tag = 1;
		v.erase(pos);
		x = a[i + m - 1];
		pos = lower_bound(v.begin(), v.end(), x);
		if(pos - v.begin() < k) {
			ans += x;
			if(!tag) ans -= v[k - 1];
		}
		else if(tag) ans += v[k - 1];
		v.insert(pos, x);
		printf("%lld ", ans);
	}
	return 0;
}

F - Xor Minimization

先建立 trie 树,然后在树上递归查询。

(u1s1,这种二进制异或题真的 trie 树板树)

点击查看代码
#include<cstdio>
#include<algorithm>
#include<algorithm>
using namespace std;
#define int long long
const int N = 150005;
int n, cnt, a[N], tr[N * 30][2];

void ins(int x) {
	int now = 0, v;
	for(int i = 29; i >= 0; i --) {
		v = x >> i & 1;
		if(!tr[now][v]) tr[now][v] = ++cnt;
		now = tr[now][v];
	}
}

int query(int num, int p) {
	if(num == -1) return 0;
	if(!tr[p][0]) return query(num - 1, tr[p][1]);
	if(!tr[p][1]) return query(num - 1, tr[p][0]);
	return (1ll << num) + min(query(num - 1, tr[p][0]), query(num - 1, tr[p][1])); 	
}

signed main() {
	int x;
	scanf("%lld", &n);
	for(int i = 1; i <= n; i ++) scanf("%lld", &x), ins(x);
	printf("%lld", query(29, 0));
	return 0;
}
posted @ 2023-02-26 11:41  Spring-Araki  阅读(29)  评论(0编辑  收藏  举报