Educational Codeforces Round 80 (Rated for Div. 2) 문제풀이
Educational Codeforces Round 80 (Rated for Div. 2)는 총 6문제였습니다.
A. Deadline
B. Yet another meme problem
C. Two arrays
D. Minmax problem
E. Messenger simulator
F. Red-Blue graph
저는 능력 부족으로 A,B,C 3문제 밖에 풀지 못했습니다... ㅠ
제가 푼 3문제에 대한 풀이를 작성해 보겠습니다.
A. Deadline
이번 대회 셋에서 가장 풀만한 문제였던 것 같습니다.
문제에서 N days 를 돌려야 돌아가는 프로그램을 x일을 투자하면 [N/(x+1)] (가우스) 로 줄어든다고 하였으므로,
' Adilbek be able to provide the generated results in no more than days?'
라는 조건을 만족하기 위해서는 N >= x + [N/(x+1)] 이 만족하는지만 따져주면 됩니다.
x 는 1~N-1 까지만 봤습니다. ( x=N이면 조건을 만족할 수 없기 때문)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
int T, N, d, temp, x; | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> T; | |
while(T--){ | |
bool flag = false; | |
temp = 987654321; | |
x = 0; | |
cin >> N >> d; | |
if(N>=d){ | |
cout << "YES" << '\n'; | |
continue; | |
} | |
while(x+1<N){ | |
x++; | |
if(d%(x+1)==0) temp = min(temp, x+(d/(x+1))); | |
else temp = min(temp, x+(d/(x+1))+1); | |
if(temp <= N){ | |
flag = true; | |
break; | |
} | |
} | |
if(flag) cout << "YES" << '\n'; | |
else cout << "NO" << '\n'; | |
} | |
return 0; | |
} |
B. Yet another meme problem
풀이를 생각하기가 굉장히 까다로운 문제였습니다.
a*b+a+b = conc(a,b) 에서 (a+1)(b+1) = conc(a,b)+1 은 어렵지 않게 유도 가능합니다.
여기서 (a+1)(b+1) = conc(a,b)+1 이 식을 잘보고 생각을 했어야 합니다.
잘 생각해보면, b = 9, 99, 999... 등 각 자리숫자가 모두 9 일 때,
LHS(좌항) : b+1 = 1000..... 의 꼴이므로 (a+1)*1000... 꼴이고,
RHS(우항) : conc(a,b)+1 은 LHS와 마찬가지로 (a+1)*1000.... 임을 알 수 있습니다.
예를 들면 아래와 같습니다.
a: 2, b: 99 일때 (a+1)(b+1) = (3)*100 = 299+1
a: 1432, b: 999 일때 (a+1)(b+1) = (1433)*1000 = 1432999+1
따라서 입력으로 A, B가 들어오면,
(1~A까지 A개 숫자) * (B보다 작거나 같은 각 자리가 9인 숫자의 개수) 가 답이됩니다.
이때 주의할 점이
(1) A,B 범위가 10^9 까지이므로 출력을 long long 형태로 해주어야하고
(2) B보다 작거나 같은 각 자리가 9인 숫자의 개수를 셀 때 정말 주의를 해야된다는 점입니다.
저는 (1),(2) 유형의 실수를 모두 했습니다.. ㅎㅎ
(2)번은 예를들어 B = 998 로 주어지면 이를 만족하는 개수는 9, 99 2개라는 점입니다.
(참고로 저는 while문 돌리면서 B 자리수 세주고, B/=10 이런식으로 진행하면서 B의 첫째자리가 9보다 크면 +1 해주었는데 그러면 998을 만족하는 개수가 3개 나왔었습니다....)
코드는 굉장히 간단합니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
long long T, n, m, cnt; | |
long long ans; | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> T; | |
while(T--){ | |
cnt = 0; | |
ans = 0; | |
bool Minus = false; | |
cin >> n >> m; | |
while(1){ | |
if(m==9 && Minus) break; | |
if(m<9) break; | |
if(m%10<9) Minus=true; | |
cnt++; | |
m/=10; | |
} | |
ans = n*cnt; | |
cout << ans << '\n'; | |
} | |
return 0; | |
} |
C. Two arrays
구현이 생각보다 어려운 문제였습니다.
문제를 정리해 생각해보면, 1~n 중 m개씩 m개씩 2번 뽑아서 array a에는 비감소(증가거나 같거나) 행렬이 되게, B에는 비증가(감소거나 같거나) 행렬이 되게 만들면 됩니다.
이때 a의 가장큰게 b의 가장작은거보다 작습니다.
잘 생각해보면 1~n개중 2*m개를 뽑아만 두면 저절로 배치 될 거라는걸 알 수 있습니다.
따라서 nH2*m 인 중복조합 문제임을 알 수 있습니다.
nH2*m = (n+2*m-1)C2*m 이므로 구하고자 하는 답은 (n+2*m-1)! / ((2*m)!(n-1)!) 입니다.
여기까지는 그럭저럭 생각만 하면 됩니다만, 이 중복 조합을 long long으로 구현하는 것이 저는 많이 까다로웠습니다.
저는 우선 factorial 을 구현하는 코드에서 착안하여 (어차피 (n+2*m-1)! 을 (n-1)! 으로 나누어 줄 것이므로) n*(n+1)*(n+2)*....*(n+2*m-1) 을 동작하는 함수를 만들었습니다.
위의 곱셈을 진행하는 과정에서 (어차피 후에 (2*m)! 을 나누어 줄 것이기 때문에) 1~2*m 중에서 위 곱셈 과정의 중간값을 나눌 수 있으면 나누어주었습니다.
long long 으로 중복조합을 구현하는 과정이 좀 어려운 문제였습니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
const int MOD = 1000000000+7; | |
int n, m, idx; | |
long long ans, last; | |
bool visited[20]; | |
long long H(int N, int a){ | |
long long res; | |
if (N == 1) | |
return N; | |
else{ | |
res = N; | |
for (int i = N - 1; i > a; i--){ | |
res *= i; | |
for (int i = 2; i <= 2*m; ++i){ | |
if(visited[i]) continue; | |
if(res%i==0){ | |
res/=i; | |
visited[i] = true; | |
} | |
} | |
if(res>MOD) res%=MOD; | |
} | |
return res%MOD; | |
} | |
} | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> n >> m; | |
ans = H(n+2*m-1, n-1); | |
cout << ans << '\n'; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!