AtCoder Beginner Contest 275 A-F 题解

比赛链接

砳赫賏,看懂扣 1(

A - Find Takahashi

模拟。

#include<cstdio>
#include<algorithm>
using namespace std;
int n, mx, id = 1;
int main() {
	int x;
	scanf("%d %d", &n, &mx);
	for(int i = 2; i <= n; i ++) {
		scanf("%d", &x);
		if(mx < x) mx = x, id = i;
	}
	printf("%d", id);
	return 0;
}

B - ABC-DEF

全部一顿取模操作就好。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
ll a, b, c, d, e, f, ans, mod = 998244353;
int main() {
	scanf("%lld %lld %lld %lld %lld %lld", &a, &b, &c, &d, &e, &f);
	a %= mod, b %= mod, c %= mod, d %= mod, e %= mod, f %= mod;
	ans = (a * b % mod * c % mod - d * e % mod * f % mod) % mod + mod;
	ans %= mod;
	printf("%lld", ans);
	return 0;
}

C - Counting Squares

枚举左上和右下两个点,在得到另外两个点,判断即可。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
int n, m, ans;

char s[15][15];

bool check(int x, int y) {
	if(x <= 9 && x > 0 && y > 0 && y <= 9 && s[x][y] == '#') return 1;
	return 0;
}

int main() {
	
	for(int i = 1; i <= 9; i ++) {
		scanf("%s", s[i] + 1);
	}
	
	for(int a = 1; a <= 9; a ++) {
		for(int b = 1; b <= 9; b ++) {
			for(int c = 1; c <= 9; c ++) {
				for(int d = 1; d <= 9; d ++) {
					if(a == c && b == d) continue;
					if(s[a][b] == '.' || s[c][d] == '.') continue;
					if(check(c - d + b, d - a + c) && check(a - d + b, b - a + c)) ans ++;
				}
			}
		}
	}
	printf("%d", ans / 4);
	return 0;
}

D - Yet Another Recursive Function

记忆化搜索,

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
ll n;

map<ll, ll> mp;

ll dfs(ll n) {
	if(mp.count(n)) return mp[n];
	if(!n) return 1;
	mp[n] = dfs(n / 2) + dfs(n / 3);
	return mp[n];
}

int main() {
	scanf("%lld", &n);
	printf("%lld", dfs(n));
	return 0;
}

E - Sugoroku 4

定义 dp[i][j] 为 花费 i 步到达 j 点的概率。

然后枚举每次的步数,分类讨论是否超过 n , 转移方程。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1005, mod = 998244353;

int n, m, K, inv, dp[N][N];

int qpow(int a, int b) {
	int res = 1;
	while(b) {
		if(b & 1) res = res * a % mod;
		a = a *a % mod, b >>= 1;
	}
	return res;
}
int ans;
signed main() {
	scanf("%lld %lld %lld", &n, &m, &K);
	inv = qpow(m, mod - 2);
	dp[0][0] = 1;
	for(int i = 0; i <= K; i ++) {
		for(int j = 0; j < n; j ++) {
			for(int k = 1; k <= m; k ++) {
				if(j + k > n) {
					dp[i + 1][2 * n - j - k] = (dp[i + 1][2 * n - j - k] + dp[i][j] * inv % mod) % mod;
				}
				else dp[i + 1][j + k] = (dp[i + 1][j + k] + dp[i][j] * inv % mod) % mod;
			}
		}
	}
	for(int i = 0; i <= K; i ++) ans = (ans + dp[i][n]) % mod;
	printf("%lld", ans);
	return 0;
}

F - Erase Subarrays

定义 dp[i][j] 为前 i 个数中保留数之和为 j 的最小操作次数。

分类讨论第 i 个数是否保留来转移,

  • 保留,dp[i][j] = min(dp[i - 1][j - a[i]])

  • 不保留,dp[i][j] = min(dp[i][j], dp[k - 1][j] + 1) (1 <= k <= i)

而观察可知,dp[i][j] 的转移只需要保留 dp[0][j]~dp[i - 1][j] 中的最小值,

因此我们再定义一个 p[j][i] 表示 dp[0][j]~dp[i][j] 的最小值。

结束。

#include<bits/stdc++.h>
using namespace std;
const int N = 3005, mod = 998244353;

int n, m, a[N], dp[N][N], p[N][N];


signed main() {
	scanf("%d %d", &n, &m);
	memset(dp, 0x3f, sizeof(dp));
	memset(p, 0x3f, sizeof(p));
	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	dp[0][0] = p[0][0] = 0;
	for(int i = 1; i <= n; i ++) {
		for(int j = 0; j <= m; j ++) {
			if(j >= a[i]) dp[i][j] = min(dp[i][j], dp[i - 1][j - a[i]]);
			
			dp[i][j] = min(dp[i][j], p[j][i - 1] + 1);
			p[j][i] = min(dp[i][j], p[j][i - 1]);
		}
	}
	
	for(int i = 1; i <= m; i ++) {
		if(dp[n][i] > 1e9) puts("-1");
		else printf("%d\n", dp[n][i]);
	}
	
	return 0;
}
posted @ 2023-02-28 22:54  Spring-Araki  阅读(28)  评论(0编辑  收藏  举报