AtCoder Beginner Contest 184
题目链接:https://atcoder.jp/contests/abc184/tasks
类似于牛客小白月赛,建议萌新们去体验一下,顺便复习四六级~
还是一样的,代码分成主体和头文件两部分,头文件在文末。
A - Determinant
给你一个2*2
的矩阵,输出它的行列式。
著名dreemoon
说过,ABC
的A
题都是printf
题。
const int MXN = 1e5 + 5;
int n, m;
int a, b, c, d;
void work() {
a = read(), b = read(), c = read(), d = read();
printf("%d\n", a * d - b * c);
}
B - Quizzes
给你一个长度为
n
n
n的字符串表示
n
n
n场比赛的结果,o
表示胜利加一分,x
表示失败减一分,0
分输了不扣分,初始时有
X
X
X分。请输出最后得分。
著名dreemoon
说过,ABC
的A
题都是for
枚举模拟题。
const int MXN = 2e5 + 5;
int n, m;
char s[MXN];
void work() {
n = read(), m = read();
scanf("%s", s);
for(int i = 0; i < n; ++i) {
if(s[i] == 'o') ++ m;
else m = max(0, m - 1);
}
printf("%d\n", m);
}
C - Super Ryuma
在一个无限二维笛卡尔系中,如果你在点 ( a , b ) (a,b) (a,b),一步之类你可以移动到满足下述条件的点 ( c , d ) (c,d) (c,d)。
- a + b = c + d a+b=c+d a+b=c+d
- a − b = c − d a-b=c-d a−b=c−d
- ∣ a − c ∣ + ∣ b − d ∣ ≤ 3 |a - c| + |b - d| \le 3 ∣a−c∣+∣b−d∣≤3
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rfSlUlfe-1607677880546)(D:\ACM\tmpFolder\markdown\我的推送\abc184_c.jpg)]
初始你在 ( r 1 , c 1 ) (r1,c1) (r1,c1),目的地是 ( r 2 , c 2 ) (r2,c2) (r2,c2),问最少移动次数。
1 ≤ r 1 , c 1 , r 2 , c 2 ≤ 1 0 9 1\le r1,c1,r2,c2\le 10^9 1≤r1,c1,r2,c2≤109.
思路
答案最多不超过三步。因为前两个条件保证每个点一步内能到两条垂直直线上的任意点。起点和目的点分别画出他们的两条直线,肯定会有交点,但是交点可能不是一个完整的格子,如果是完整的格子,两步内就肯定可以到达了。
所以本题只需判断两个点能否一步走到,否则看两步能否走到,否则输出三步即可。
const int MXN = 2e5 + 5;
int n, m;
class node{
public:
int a, b;
void Rd() {
a = read(), b = read();
}
};
node A, B;
int ans;
int one_step(node A, node B) {
if(A.a + A.b == B.a + B.b) return 1;
if(A.a - A.b == B.a - B.b) return 2;
if(abs(A.a - B.a) + abs(A.b - B.b) <= 3) return 3;
return 0;
}
void work() {
A.Rd(), B.Rd();
if(A.a == B.a && A.b == B.b) ans == 0;
else if(one_step(A, B)) ans = 1;
else if((A.a + A.b) % 2 == (B.a + B.b) % 2) ans = 2;//走两次直线
else {
ans = 3;
rep(i, -3, 4) {
rep(j, -3, 4) {
if(abs(i) + abs(j) > 3) continue;
A.a += i, A.b += j;
if(one_step(A, B)) ans = 2;
A.a -= i, A.b -= j;
}
}
}
printf("%d\n", ans);
}
D - increment of coins
一个黑箱里面有三色糖果,初始时分别有
a
,
b
,
c
a,b,c
a,b,c个。每次等概率取出一个糖果,再额外放回去一个这种颜色的糖果。问期望次数使得某种颜色糖果个数达到100
。
1 ≤ a , b , c ≤ 99 , a + b + c ≥ 1 1\le a,b,c\le 99,a+b+c\ge 1 1≤a,b,c≤99,a+b+c≥1.
思路
推荐练习题HDU6558
。
d
p
[
a
]
[
b
]
[
c
]
dp[a][b][c]
dp[a][b][c]表示现在糖果数量状态是
(
a
,
b
,
c
)
(a,b,c)
(a,b,c)要达到某种糖果100
个需要的期望次数。
状态转移现在只有三种,选出 a , b , c a,b,c a,b,c,概率分别是 a a + b + c , b a + b + c , c a + b + c \frac a{a+b+c},\frac b{a+b+c},\frac c{a+b+c} a+b+ca,a+b+cb,a+b+cc。
d p [ a ] [ b ] [ c ] = ( a ∗ d p [ a + 1 ] [ b ] [ c ] + b ∗ d p [ a ] [ b + 1 ] [ c ] + c ∗ d p [ a ] [ b ] [ c + 1 ] ) / ( a + b + c ) + 1 dp[a][b][c] = (a * dp[a + 1][b][c] + b * dp[a][b + 1][c] + c * dp[a][b][c + 1])/(a + b + c) + 1 dp[a][b][c]=(a∗dp[a+1][b][c]+b∗dp[a][b+1][c]+c∗dp[a][b][c+1])/(a+b+c)+1
期望
d
p
dp
dp经典写一个递归的dfs
求出或者迭代法求出。
一般都是正向推概率,反向推期望。
int a, b, c;
double dp[101][101][101];
const double eps = 1e-8;
double dfs(int a, int b, int c) {
if(fabs(dp[a][b][c]) > eps) return dp[a][b][c];
if(a == 100 || b == 100 || c == 100) return dp[a][b][c] = 0;
return dp[a][b][c] = (a * dfs(a + 1, b, c) + b * dfs(a, b + 1, c) + c * dfs(a, b, c + 1))/(a + b + c) + 1;
}
void work() {
a = read(), b = read(), c = read();
dfs(a, b, c);
printf("%.9f\n", dp[a][b][c]);
}
---
hdu6558代码
int n, m;
double dp[MXN];
double dfs(int p) {
if(p >= 1000) return 100.0/n;
if(fabs(dp[p] - 0) > 1e-9) return dp[p];
dp[p] = (n*(p+(1000-p)*(dfs(p+20)+1))/1000.0+
(100-n)*(1+dfs(p+15)))/100.0;
return dp[p];
}
double dfs2(int p) {
if(p >= 1000) return 100.0/n;
if(fabs(dp[p] - 0) > 1e-9) return dp[p];
dp[p] = 1 + (n*(1000-p)*(dfs2(p+20))/1000.0+
(100-n)*(dfs2(p+15)))/100.0;
return dp[p];
}
int main() {
int tim = read(), cas = 0;
while(tim --) {
n = read();
printf("Case %d: ", ++ cas);
clr(dp, 0);
dfs2(20);
printf("%.10f\n", dp[20]);
}
return 0;
}
E - Third Avenue
H
∗
W
H*W
H∗W矩阵中起点S
,终点G
,有26种颜色传送门a
,…,z
,障碍物#
,平地.
。
- 障碍物无论如何都不能移动过去
1
秒内可以选择上下左右移动一步- 如果身处
x
色传送门,1
秒内可以移动到任意一个同色传送门。
问最短时间从起点到达终点。永远都到不了就输出-1
。
1 ≤ H , W ≤ 2000 1\le H,W\le 2000 1≤H,W≤2000.
思路
BFS
直接莽,暴力冲就完事了。对传送门用26
个vector
存储起来即可。
BFS
的时候枚举四个方向移动或者移动到所有可以移动到的传送门位置。
同时对移动过的点打标记,不能走到标记过的点。
注意移动过的传送门一定要及时清空,不然会TLE
。
const int MXN = 2e3 + 5;
int n, m;
char ar[MXN][MXN];
int vis[MXN][MXN];
vector<pii> az[26];
bool out(int a, int b) {
return a < 1 || a > n || b < 1 || b > m || ar[a][b] == '#';
}
void work() {
queue<pii> Q;
n = read(), m = read();
rep(i, 1, n + 1) {
scanf("%s", ar[i] + 1);
rep(j, 1, m + 1) {
if(ar[i][j] == 'S') {
Q.push(mk(i, j));
vis[i][j] = 1;
}
if(islower(ar[i][j])) az[ar[i][j]-'a'].eb(mk(i, j));
}
}
while(!Q.empty()) {
pii u = Q.front();
if(ar[u.fi][u.se] == 'G') break;
Q.pop();
rep(i, -1, 2) {
if(i == 0) continue;
int px = u.fi + i, py = u.se;
if(!out(px, py) && vis[px][py] == 0) {
vis[px][py] = vis[u.fi][u.se] + 1;
Q.push(mk(px, py));
}
px = u.fi, py = u.se + i;
if(!out(px, py) && vis[px][py] == 0) {
vis[px][py] = vis[u.fi][u.se] + 1;
Q.push(mk(px, py));
}
}
if(islower(ar[u.fi][u.se]) && !az[ar[u.fi][u.se] - 'a'].empty()) {
for(pii x: az[ar[u.fi][u.se] - 'a']) {
if(vis[x.fi][x.se] == 0) {
vis[x.fi][x.se] = vis[u.fi][u.se] + 1;
Q.push(mk(x.fi, x.se));
}
}
az[ar[u.fi][u.se] - 'a'].clear();
}
}
if(Q.empty()) printf("-1\n");
else printf("%d\n", vis[Q.front().fi][Q.front().se] - 1);
}
F - Programming Contest
有 n n n个糖果,每个糖果美味度和容量都是 a i a_i ai,有一个容量为 T T T的包裹,问可以装的糖果的美味度之和的最大值。
1 ≤ n ≤ 40 , 1 ≤ a i ≤ 1 0 9 1\le n\le 40, 1\le a_i\le 10^9 1≤n≤40,1≤ai≤109.
思路
这是一道meet in middle
题目。
把 n n n个糖果分成两半,然后 O ( 2 20 ) O(2^{20}) O(220)枚举每一半所有组合存起来,然后排个序,双指针或者二分求一下最大值即可。
const int MXN = 1e2 + 5;
int n, m;
int ar[MXN];
int64 T, ans;
vector<int> vs, vt;
vector<int64> sum, tum;
void work() {
n = read();
T = read();
for(int i = 1; i <= n; ++i) ar[i] = read();
sort(ar + 1, ar + n + 1);
for(int i = 1; i <= n; ++i) {
if(i <= n / 2) vs.eb(ar[i]);
else vt.eb(ar[i]);
}
n = vs.size();
m = 1 << n;
for(int i = 1; i < m; ++i) {
int64 res = 0;
for(int j = 0; j < n; ++j)
if(i & (1 << j)) res += vs[j];
if(res <= T) ans = max(ans, res);
if(ans == T) break;
if(res < T) sum.eb(res);
}
n = vt.size();
m = 1 << n;
for(int i = 1; i < m; ++i) {
int64 res = 0;
for(int j = 0; j < n; ++j)
if(i & (1 << j)) res += vt[j];
if(res <= T) ans = max(ans, res);
if(ans == T) break;
if(res < T) tum.eb(res);
}
sort(all(tum));
for(int x: sum) {
if(x > T) continue;
int p = upper_bound(all(tum), T - x) - tum.begin();
if(p != 0) ans = max(ans, tum[p - 1] + x);
if(ans == T) break;
}
printf("%lld\n", ans);
}
头文件
#include <bits/stdc++.h>
#define fi first
#define se second
#define o2(x) (x) * (x)
#define mk make_pair
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a), (b), sizeof((a)))
#define rep(i, s, t) for(register int i = (s), LIM=(t); i < LIM; ++i)
#define per(i, s, t) for(register int i = (s), LIM=(t); i >= LIM; --i)
#define GKD std::ios::sync_with_stdio(false);cin.tie(0)
#define my_unique(x) sort(all(x)), x.erase(unique(all(x)), x.end())
using namespace std;
typedef long long LL;
typedef long long int64;
typedef unsigned long long uint64;
typedef pair<int, int> pii;
// mt19937 rng(time(NULL));//std::clock()
// mt19937_64 rng64(chrono::steady_clock::now().time_since_epoch().count());
// shuffle(arr, arr + n, rng64);
inline int64 read() {
int64 x = 0;int las = 0;char ch = getchar();
while (ch < '0' || ch > '9') las |= (ch == '-'), ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch =
getchar(); return x = las ? -x : x;
}
inline void write(int64 x, bool las = true) {
if (x == 0) {putchar('0'); if(las)putchar('\n');else putchar(' ');return;}
if (x < 0) {putchar('-');x = -x;}
static char s[23];
int l = 0;
while (x != 0)s[l++] = x % 10 + 48, x /= 10;
while (l)putchar(s[--l]);
if(las)putchar('\n');else putchar(' ');
}
int lowbit(int x) { return x & (-x); }
template <class T>
T big(const T &a1, const T &a2) {return a1 > a2 ? a1 : a2;}
template <class T>
T sml(const T &a1, const T &a2) {return a1 < a2 ? a1 : a2;}
template <typename T, typename... R>
T big(const T &las, const R &... r) {return big(las, big(r...));}
template <typename T, typename... R>
T sml(const T &las, const R &... r) {return sml(las, sml(r...));}
void debug_out() { cout << '\n'; }
template <typename T, typename... R>
void debug_out(const T &las, const R &... r) {
cout << las << " ";
debug_out(r...);
}
#ifdef LH_LOCAL
#define debug(...) cout << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#else
#define debug(...) ;
#endif
/*================Header Template==============*/
const int mod = 998244353;// 998244353
int ksm(int a, int64 b, int kmod = mod) {int res = 1;for(;b > 0;b >>= 1, a = (int64)a * a % kmod) if(b &1) res = (int64)res * a % kmod;return res;}
const int INF = 0x3f3f3f3f;
---
将上面的代码填入此处
---
int main() {
#ifdef LH_LOCAL
freopen("D:/ACM/mtxt/in.txt", "r", stdin);
// freopen("D:/ACM/mtxt/out.txt", "w", stdout);
#endif
for(int cas = 1, tim = 1; cas <= tim; ++ cas) {
work();
}
#ifdef LH_LOCAL
cout << "time cost:" << 1.0 * clock() / CLOCKS_PER_SEC << "s" << endl;
#endif
return 0;
}