본문 바로가기
PS/AtCoder

AtCoder ABC 234 풀이

by jaehoonChoi 2022. 10. 7.

https://atcoder.jp/contests/abc234/tasks

 

Tasks - AtCoder Beginner Contest 234

AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.

atcoder.jp

 

 

A.

구하라는 함수값을 출력해주면 됩니다.

#include <bits/stdc++.h>
using namespace std;

int f(int x) {
	return x * x + 2 * x + 3;
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	int t; cin >> t;
	cout << f(f(f(t) + t) + f(f(t))) << '\n';
}

 

 

 

B.

두 쌍의 거리의 최대를 O(N^2)에 찾아줄 수 있습니다.

#include <bits/stdc++.h>
using namespace std;

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	int n; cin >> n;
	vector<double>x(n), y(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i] >> y[i];
	}
	double ans = 0;
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			ans = max(ans, hypot(x[j] - x[i], y[j] - y[i]));
		}
	}
	cout << fixed << setprecision(10);
	cout << ans << '\n';
}

 

 

 

C.

0과2만 이용해 k번째 숫자를 구해야 합니다. 0과 2를 0과 1로 바꿔도 됩니다.

그럼 k번째로 작은 수는 이진법상 k번째 수 입니다. 따라서 k의 2진법 표현에서

1만 2로 바꿔주면 됩니다.

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve(ll x) {
	vector<int>v;
	while (x) {
		v.push_back(x % 2);
		x >>= 1;
	}
	for (int i = v.size() - 1; i >= 0; i--) {
		cout << (v[i] == 1 ? 2 : 0);
	}
	
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	ll x; cin >> x;
	solve(x);
}

 

 

 

D.

N-k번동안 k번째로 큰 수를 찾아야 합니다. minheap 우선순위 큐로 관리해주면 쉽습니다.

O((N-K)logK)에 해결할 수 있습니다.  

#include <bits/stdc++.h>
using namespace std;

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	int n, k;
	cin >> n >> k;
	vector<int>p(n);
	for (int i = 0; i < n; i++)cin >> p[i];
	priority_queue<int>pq;
	for (int i = 0; i < k; i++) {
		pq.push(-p[i]);
	}
	cout << -pq.top() << '\n';
	for (int i = k; i < n; i++) {
		if (-pq.top() < p[i]) {
			pq.pop();
			pq.push(-p[i]);
		}
		cout << -pq.top() << '\n';
	}
}

 

 

 

 

E.

각 자릿수들이 등차수열을 이루게 만들어야 합니다.

 

관찰1. 공차의 철댓값이 1이상인 경우는 987654321이 최대입니다.

즉 10^17까지 있을 때 987654321 이후로는 모든 값이 같은 경우밖에 없습니다.

 

관찰2. 따라서 이러한 문자열의 개수가 별로 없다는 것을 알 수 있습니다.

따라서 모든 공차에 따른 문자열을 생성하고 set으로 관리해주면 됩니다.

답은 set에서 lowerbound를 찾아주면 됩니다. 

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

set<ll> make() {
    set<ll> s;
    for (int x = 1; x <= 9; x++) {
        for (int d = -9; d < 9; d++) {
            string t;
            int dg = x;
            for (int len = 0; len < 18; len++) {
                t.push_back(dg + '0');
                s.insert(stoll(t));
                dg += d;
                if (dg < 0 || dg > 9)break;
            }
        }
    }
    return s;
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
    ll x; cin >> x;
    set<ll> S = make();
    cout << *(S.lower_bound(x)) << '\n';
}

 

 

 

 

F. 

a부터 z를 1~26로 보고 사용한 횟수를 cnt로 저장해둡니다.

dp[i][j]를 i번 문자열까지 사용해서 길이 j를 만드는 경우의 수로 정의합니다.

dp[i][j]=sum (1<=k<=p)(dp[i-1][j-k])*(jCk)가 됩니다. 여기서 p는 min(j, cnt[i])가 됩니다.

이를 갱신하는건 O(N*(cnt1+....+cnt26))=O(N^2)에 해결할 수 있습니다.

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 998244353;
ll dp[27][5005];
ll c[5005][5005];

void make_table() {
	for (int i = 0; i <= 5000; i++) {
		for (int j = 0; j <= i; j++) {
			if (i == j || j == 0) {
				c[i][j] = 1;
			}
			else {
				c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	string s; cin >> s;
	int N = s.size();
	vector<int>cnt(28);
	for (auto i : s) {
		cnt[i - 'a' + 1]++;
	}
	dp[0][0] = 1;
	make_table();
	for (int i = 1; i <= 26; i++) {
		for (int j = 0; j <= N; j++) {
			for (int k = 0; k <= min(j, cnt[i]); k++) {
				dp[i][j] += dp[i - 1][j - k] * c[j][k];
				dp[i][j] %= mod;
			}	
		}
	}
	ll ans = 0;
	for (int i = 1; i <= N; i++) {
		ans += dp[26][i];
		ans %= mod;
	}
	cout << ans << '\n';
}

 

 

'PS > AtCoder' 카테고리의 다른 글

AtCoder ABC 282 D, E  (1) 2022.12.22
AtCoder ABC 256 풀이  (0) 2022.10.22
AtCoder ABC 238 D,E  (0) 2022.10.02
AtCoder ABC 239 풀이  (0) 2022.10.01
AtCoder ABC 242 풀이  (0) 2022.09.28

댓글