Programming

[CF] Round #556 (Div. 2) _ 210124

minigb 2021. 4. 26. 11:56

(2021년 1월 25일에 작성한 글입니다.)

 

 

Standings - Codeforces Round #556 (Div. 2) - Codeforces

 

codeforces.com

학회 코포 스터디에서 버추얼로 풀었다.

A.

A가 A 같지가 않았다

문제 이해하는데 꽤 시간 걸렸지만 그래도 구현은 쉬웠다.

구매 가격 중 가장 낮은거, 판매 가격 중 가장 높은 걸 비교해서

만약 더 비싸게 팔 수 없으면 아무 처리도 하지 않고,

더 비싸게 팔 수 있다면 최대한 구매한 뒤 되팔면 된다.

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	ll N, M, K;

	cin >> N >> M >> K;
	vector<ll> buy(N), sell(M);
	for (int i = 0; i < N; i++) {
		cin >> buy[i];
	}
	sort(buy.begin(), buy.end());
	for (int i = 0; i < M; i++) {
		cin >> sell[i];
	}
	sort(sell.begin(), sell.end(), greater<>());

	ll stock = 0;
	if (buy[0] < sell[0]) {
		stock += K / buy[0];
		K %= buy[0];
		K += stock * sell[0];
	}

	cout << K << ENDL;

	return 0;
}

B.

ㅋㅋㅋㅋA번에서 약간 당황하고 B번 보니까 더 당황스러웠다.

처음에는 N이 작으니까 모든 빈칸에 대해 BFS를 돌려야 되는 줄 알았다

근데 빠르게 늘어나는 ac들을 보면서 그건 아니라는 걸 느꼈고

그냥 왼쪽 위부터 확인하면서 만약 빈칸이 있으면

그게 십자가의 위쪽 부분이 되어야 한다 무조건.

그렇게 처리 해서 만약 타일을 다 채울 수 있으면 YES

아니면 NO

int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int N;

	cin >> N;
	vector<vector<char>> arr(N + 5, vector<char>(N + 5));
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			cin >> arr[i][j];
			arr[i][j] = arr[i][j] == '.' ? 1 : 0;
		}
	}

	bool ans = true;
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (arr[i][j]) {
				if (arr[i + 1][j - 1] && arr[i + 1][j] && arr[i + 1][j + 1] && arr[i + 2][j]) {
					arr[i][j] = 0;
					arr[i + 1][j - 1] = 0;
					arr[i + 1][j] = 0;
					arr[i + 1][j + 1] = 0;
					arr[i + 2][j] = 0;
				}
				else {
					ans = false;
					break;
				}
			}
		}
	}

	if (ans) {
		cout << "YES" << ENDL;
	}
	else {
		cout << "NO" << ENDL;
	}
	return 0;
}

C.

이거 진짜 재밌는 문제였다

인접한 소수들 간의 차는 2->3을 제외하면 모두 2의 배수이다

2를 제외한 소수들은 모두 홀수니까!

우왕...

그래서 앞에 prefix가 2->3이 되도록 만들어주고,

그 후에는 2를 모두 출력하고, 1을 모두 출력하면 된다.

시작은 수열을 {2, 1, ...}로 시작해야 한다.

그래야 prefix가 2, 3, .. 이렇게 나오니까.

근데...ㅋㅋㅋㅋ

지금 보니까 엄청 돌아갔네...

처음에는 1의 개수가 홀수일 때 / 짝수일 때를 나눠서

1이 짝수개면 시작이 1 1 2 1 ..

홀수개이면 2 1 2 ... 1 ... 이렇게 되야 한다고 생각했는데

아니어서 케이스를 안 나눴다.

그리고 결국 ac받은 코드는

소수들을 구해놓고 인접한 소수 간의 차이를 계산해서

2 한번 or 1 두 번 출력할때마다 그 차이에서 빼준 방식이다..

왜 그랬지?? 그럴 필요가 전혀 없다

그냥 2, 1, 2, ..., 1, ...

이런식으로 출력하면 된다

vector<int> primeNums;
vector<bool> isPrime;
void era(ll MAX)
{
	isPrime.resize(MAX + 1, true);
	ll i, j;

	isPrime[0] = isPrime[1] = false;

	for (i = 2; i <= MAX; i++) {
		if (isPrime[i]) {
			primeNums.push_back(i);
			for (j = i * i; j <= MAX; j += i) {
				isPrime[j] = false;
			}
		}
	}
}

int main()
{
	era(400040);
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int N;

	cin >> N;
	int cnt[3] = {0};
	for (int i = 0; i < N; i++) {
		int a; cin >> a;
		cnt[a]++;
	}

	if (cnt[1] == N) {
		for (int i = 0; i < N; i++) {
			cout << 1 << ' ';
		}
		return 0;
	}
	if (cnt[2] == N) {
		for (int i = 0; i < N; i++) {
			cout << 2 << ' ';
		}
		return 0;
	}

	cnt[2]--;
	cout << 2 << ' ';
	cnt[1]--;
	cout << 1 << ' ';

	for (int i = 2; ; i++) {
		int diff = primeNums[i] - primeNums[i - 1];
		while (diff && cnt[2]) {
			cnt[2]--;
			diff -= 2;
			cout << 2 << ' ';
		}
		while (diff && cnt[1] >= 2) {
			cnt[1] -= 2;
			diff -= 2;
			cout << 1 << ' ' << 1 << ' ';
		}

		if (cnt[2] == 0 && cnt[1] <= 1) {
			if (cnt[1]) {
				cout << 1 << ' ';
			}
			break;
		}
	}

	return 0;
}