A - In-game Chat
Problem - A - Codeforces
codeforces.com
생략
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t; cin >> t;
while (t--)
{
int n; string s;
cin >> n >> s;
int cnt = 0;
for (int i = s.size() - 1; i >= 0; i--)
{
if (s[i] == ')') cnt++;
else break;
}
if (cnt > n - cnt) cout << "Yes\n";
else cout << "No\n";
}
}
|
B - Fair Numbers
Problem - B - Codeforces
codeforces.com
어떤 양의 정수가 0을 제외한 모든 자릿수로 나누어 떨어지면 이 수를 fair하다고 한다.
\(n\)이 주어지면, \(n\)보다 크거나 같은 가장 작은 fair한 수를 출력해야 한다.
어떤 수가 1~9까지 모든 수를 자릿수로 가지고 있다고 생각해보자.
이 수는 2520으로 나누어 떨어져야 한다는 사실을 알 수 있다.
다시 말하면, 답은 \(n\)이상 \(n+2520\)미만의 수 중 하나이므로, 완전탐색으로 충분히 답을 찾을 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t; cin >> t;
while (t--)
{
ll n; cin >> n;
while (true)
{
bool flag = true;
ll x = n;
while (x)
{
if (x % 10 && n % (x % 10)) flag = false;
x /= 10;
}
if (flag)
{
cout << n << '\n';
break;
}
n++;
}
}
}
|
A - Peaceful Rooks
Problem - A - Codeforces
codeforces.com
\(n \times n\) 크기의 체스보드가 있다.
이 체스보드에 \(m\)개의 룩이 서로를 공격하지 않는 위치에 놓여 있다.
이 룩들을 모든 시점에 서로 공격받지 않도록 하면서, 모두 정대각선 (\((x, x)\))위치에 놓이게 하기 위해 룩을 이동해야 하는 최소 횟수를 알아내야 한다.
어떤 룩이 \((x,y)\)에 있다고 가정하자.
이 룩을 이동하기 위해서는 \((y, a)\)와, \((b, x)\)에 있는 룩 중 하나를 먼저 이동해야 한다는 사실을 알 수 있다.
만약 \((y,a)\)에 룩이 없다면 현재 룩을 \((y,y)\)로, \((b,x)\)에 룩이 없다면 현재 룩을 \((x,x)\)로 바로 이동시키는 것이 이득임을 알 수 있다.
그러면 각각의 룩을 정점으로, 현재 룩을 이동하기 위해 먼저 움직여야 하는 룩을 간선으로 하는 그래프를 만들 수 있다.
이 그래프는 1개 이상의 컴포넌트로 이루어져 있을 것이다.
정점이 1개인 컴포넌트는 정대각선에 있는 룩이므로 무시하면 되고,
그렇지 않은 컴포넌트는 컴포넌트의 크기를 답에 더해주면 된다.
하지만 만약 어떤 컴포넌트가 사이클을 이룬다면, 이 컴포넌트는 모든 룩이 제자리를 찾기 위해서 임의의 한 룩을 다른 위치로 이동 시켜주어야 한다. 따라서 답에 1을 더해주어야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
int n, m;
int x[100001], y[100001];
int xr[100001], yr[100001];
int cache[100001];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t; cin >> t;
while (t--)
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
xr[i] = 0, yr[i] = 0;
cache[i] = 0;
}
for (int i = 1; i <= m; i++)
{
cin >> x[i] >> y[i];
xr[x[i]] = i;
yr[y[i]] = i;
}
int ans = 0;
for (int i = 1; i <= m; i++)
{
if (cache[i]) continue;
cache[i] = 1;
int ci = i;
int cx = x[i], cy = y[i];
if (cx == cy) continue;
int res = 1;
bool isLoop = false;
while (xr[y[ci]])
{
ci = xr[y[ci]];
if (cache[ci])
{
isLoop = true;
break;
}
res++;
cache[ci] = 1;
cx = x[ci], cy = y[ci];
}
ci = i;
if (!cache[yr[x[ci]]])
{
while (yr[x[ci]])
{
ci = yr[x[ci]];
res++;
cache[ci] = 1;
cx = x[ci], cy = y[ci];
}
}
if (isLoop) ans += res + 1;
else ans += res;
}
cout << ans << '\n';
}
}
|
B - Grime Zoo
Problem - B - Codeforces
codeforces.com
0과 1과 ?로 이루어진 문자열이 주어진다.
?에는 0또는 1을 임의로 넣을 수 있다.
이 문자열의 모든 길이가 2인 부분수열에 대해,
부분수열이 "01"이라면 점수에 \(x\)를 더하고, 부분수열이 "10"이라면 점수에 \(y\)를 더한다.
받을 수 있는 최소 점수를 구해야 한다.
문자열의 모든 ?를 앞과 뒤 두 부분으로 나누자. (각 부분의 크기는 0일 수 있다)
\(x < y\)라면 앞 부분을 전부 0으로, 뒷 부분을 전부 1로 하는 것이,
그렇지 않다면 앞 부분을 전부 1로, 뒷 부분을 전부 0으로 하는 것이 무조건 이득임을 관찰을 통해 알 수 있다.
부분합이나 세그트리 등을 이용해 모든 경우에 대해 답을 구한다음, 그 중 최소값이 답이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
const ll INF = numeric_limits<ll>::max();
const int N = 100001;
string s;
ll x, y;
ll segTree[2][N];
void update(ll *segTree, int idx, ll v)
{
while (idx <= s.size())
{
segTree[idx] += v;
idx += idx & -idx;
}
}
ll getVal(ll* segTree, int idx)
{
ll res = 0;
while (idx)
{
res += segTree[idx];
idx -= idx & -idx;
}
return res;
}
ll getVal(ll* segTree, int i, int j)
{
return getVal(segTree, j) - getVal(segTree, i - 1);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> s;
cin >> x >> y;
ll ans = 0;
for (int i = 0; i < s.size(); i++)
{
int idx = i + 1;
if (s[i] != '1')
{
ans += getVal(segTree[1], 1, idx - 1) * y;
update(segTree[0], idx, 1);
}
else
{
ans += getVal(segTree[0], 1, idx - 1) * x;
update(segTree[1], idx, 1);
}
}
ll res = ans;
for (int i = 0; i < s.size(); i++)
{
int idx = i + 1;
if (s[i] != '?') continue;
res -= getVal(segTree[1], 1, idx - 1) * y;
res -= getVal(segTree[1], idx + 1, s.size()) * x;
update(segTree[0], idx, -1);
res += getVal(segTree[0], 1, idx - 1) * x;
res += getVal(segTree[0], idx + 1, s.size()) * y;
update(segTree[1], idx, 1);
ans = min(ans, res);
}
for (int i = 0; i < s.size(); i++)
{
int idx = i + 1;
if (s[i] != '?') continue;
res -= getVal(segTree[0], 1, idx - 1) * x;
res -= getVal(segTree[0], idx + 1, s.size()) * y;
update(segTree[1], idx, -1);
res += getVal(segTree[1], 1, idx - 1) * y;
res += getVal(segTree[1], idx + 1, s.size()) * x;
update(segTree[0], idx, 1);
ans = min(ans, res);
}
cout << ans;
}
|
C - Poman Numbers
Problem - C - Codeforces
codeforces.com
\(n\)길이의 문자열 \(S\)가 주어진다.
이 문자열의 값 \(f(S)\)를 다음과 같이 결정할 수 있다.
1. \(|S| > 1\)이라면, 임의의 \(1 \le m \le |S|\)을 고른다. \(f(S) = -f(S[1,m]) + f(S[m+1,|S|])\) 이다.
2. 그렇지 않다면, \(f(S) = 2^c\)이다.
어떤 수 \(T\)가 주어졌을 때, \(f(S) = T\)가 될 수 있는지 여부를 알아내야 한다.
함수가 복잡하게 쓰여 있지만, 관찰을 통해 다음과 같은 사실을 알 수 있다.
1. 가장 뒤에 있는 문자의 부호는 무조건 +이다.
2. 2번째로 뒤에 있는 문자의 부호는 무조건 -이다.
3. 그 외의 문자의 부호는 +, - 두 경우 모두 가능하다.
따라서 문제를 2의 제곱꼴인 양의 정수 \(n-2\)개가 주어졌을 때, 이 정수들을 더하거나 빼서 \(X\)를 만들 수 있는지 여부를 묻는 문제로 바꿔 생각할 수 있다. (\(X\)는 \(T\)에서 뒤에 있는 2개의 문자를 더하고 뺀 값이다.)
그리디하게 큰 수 부터 \(X\)를 만들어 가면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll gcd(ll a, ll b) { for (; b; a %= b, swap(a, b)); return a; }
ll n, T;
string s;
ll cnt[26];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> T;
cin >> s;
for (int i = 0; i + 2 < n; i++)
{
cnt[s[i] - 'a']++;
}
T += (1ll << (s[n - 2] - 'a'));
T -= (1ll << (s[n - 1] - 'a'));
for (int i = 25; i >= 0; i--)
{
for (int j = 0; j < cnt[i]; j++)
{
if (T > 0) T -= (1ll << i);
else T += (1ll << i);
}
}
bool ans = (T == 0);
if (ans) cout << "Yes";
else cout << "No";
}
|
D - The Thorny Path
Problem - D - Codeforces
codeforces.com
E - No Game No Life
Problem - E - Codeforces
codeforces.com
추가 예정
F - My Beautiful Madness
Problem - F - Codeforces
codeforces.com
추가 예정
'문제 풀이 > Codeforces' 카테고리의 다른 글
Codeforces Round #693 (Div. 3) (0) | 2021.01.05 |
---|---|
Educational Codeforces Round 101 (0) | 2020.12.29 |
Educational Codeforces Round 100 (0) | 2020.12.19 |
Codeforces Round #690 (Div. 3) (0) | 2020.12.17 |
Codeforces Round #689 (Div. 2) (0) | 2020.12.13 |