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