A. Ahahahahahahahaha

n / 2 이하로만 뽑으면 됐다. 0과 1밖에 안나오기 때문에 0이 n / 2 이상 개수가 있었으면 n / 2개만큼의 0을 출력해주면 되고 0이 n / 2 미만이었다면 1이 n / 2 + 1 개 있다는 것이므로 1을 n / 2 + 1 만큼 출력하면 되는 문제였다.

B. Big Vova

안그래도 영어라 읽기 힘든데 무려 한 문단이 문제와 관련없었다. 맨 앞에 오는 숫자는 반드시 a 배열중에서 가장 큰 숫자여야 했다. GCD(b1)에서 그 수 자체가 c1이 되는데 사전순으로 가장 크게 될려면 가장 큰 숫자가 왔어야 하기 때문이다.

처음에 풀면서 n^2에 gcd까지 구하는 풀이가 생각났는데 n제한이 10^5인줄 알고 이 방법을 쓰지 않고 다른 걸 찾다가 시간을 많이 썼다. 10^3인걸 잘 봤으면 이렇게 풀고 빨리 끝냈을 수 있을 것 같다.

C. Chocolate Bunny

크기가 다른 두 숫자를 순서 바꿔서 한번 씩 mod연산 하면 둘 중 작은 값이 두 숫자 중 작은 값이다. 이를 이용해서 풀 수 있었다.

B. Power Sequence

https://codeforces.com/contest/1397/problem/B

처음에 너무 난해했다. 모든 경우를 다 하지 않고 어떻게 구할 수 있는지 고민을 많이 했다. 고민을 하던 중에 c가 2만 되더라도 n이 10^5는 고사하고 n이 30만 되도 10^9를 넘어 사실상 c가 1일때만 10^5만큼 해봐야하고 그 이상일 땐 정말 적은 양만 탐색해보면 되는 문제였다.

C. Multiples of Length

https://codeforces.com/contest/1397/problem/C

어떻게 풀어야 할지 감이 안왔다. 정렬 후 세그먼트 트리로 풀 수 있을까 생각해봤는데 그렇게 하더라도 경우의 수가 너무 많았다. 도저히 생각이 안나서 다른사람 코드를 봤는데 너무 간단해서 허무했다. 1~n-1까지 각 값에 n-1을 곱해 더하면 arr[i] * (n-1) + arr[i] 하면 1~n-1까지의 값이 모두 arr[i] * n 이 되고 n~n까지는 구간의 길이가 1이라 무엇이든 곱해도 되니 arr[last] * (n-1) + arr[last] 로 arr[last] * n 을 만든다. 마지막으로 1~n까지에 -1 * arr[i] * n으로 더해주면 모두 0을 만들 수 있었다. 코드포스식 쉬운 문제들은 이런식의 접근을 해야겠다는 생각을 했다.

D. Stoned Game

https://codeforces.com/contest/1397/problem/D

그리디인건 알겠는데 또 감이 안왔다. 백준에 많은 돌 게임 문제가 있었는데 이건 좀 유형이 다르고 DP로 풀 수 있는 문제였다. 다른 사람의 풀이를 보고 감을 잡고 풀 수 있었다. 먼저 가장 간단하게 생각하면 돌 개수 총 합이 홀수개면 T가 이기고 짝수면 HL이 이긴다. 여기서 변수는 T나 HL이 뽑은 게 마지막 남은 pile이어서 돌이 남았더라도 뽑을 수 없게 되면 돌의 개수와 상관없이 그 돌을 점유하고 있던 플레이어가 이긴다. 이러한 상황은 T만 만들 수 있다. 이 상황이 나오려면 가장 큰 pile이 나머지 pile의 모든 합보다 크면 T가 그 pile만 계속 점유하면 이기기 때문에 이 경우를 예외처리하고 이외에는 짝수홀수 경우로 답을 구했다.

A. Minimum Binary Number



처음 문제를 봤을 때 operation을 1번이나 제한적으로 쓸 수 있다고 생각해서 A 부터 엄청 어려운 게 나왔구나 했는데 계속 사용이 가능했다. 보면 나올 수 있는 최소의 값은 0의 개수를 세어주고 그 뒤에 1을 붙이거나, input이 1 0 인 예외를 처리해주면 통과되었다. 

#include <iostream>
#include <string>
using namespace std;
char arr[1001];
int main(void) {
       int n;
       cin >> n;
       string s;
       cin >> s;
       if (n == 1 && s[0] == '0') {
               cout << '0' << endl;
               return 0;
       }
       int cnt = 0;
       for (int i = 0; i < n; ++i) {
               if (s[i] == '0') {
                      cnt++;
               }
       }
       cout << '1';
       for (int i = 0; i < cnt; ++i) {
               cout << '0';
       }
       return 0;
}



B. Lara Croft and the New Game


처음 문제를 봤을 때 x좌표와 y좌표를 k,n,m에 대해서 나타낼 수 있을 걸 알았지만 교육적인 목적에서 직접 경로를 탐색하는 코드를 짜보았다. 무슨 생각인 진 모르겠지만 k가 10^9보다 작다고 생각해서 시간초과는 안 날 것이라 생각했는데 짜놓고 제출하고 시간초과가 나서 생각해보니 최악의 경우 INT32_MAX-1까지 가능했다. 20억번이므로 대략 20초가 걸리므로 당연히 시간초과
그래도 구현한 코드를 올려보면 

#include <iostream>
#include <string>
using namespace std;
int c;
int x = 1, y = 1;
bool inturrupt() {
       if (x == 1 && y == 2) {
               cout << x << ' ' << y << endl;
               return 1;
       }
       if (c == 0) {
               cout << x << ' ' << y << endl;
               return 1;
       }
       c--;
       return false;
};
void print() {
       cout << x << ' ' << y << endl;
}
int main(void) {
       int a, b;
       cin >> a >> b >> c;
       a--;
       b--;
       //print();
       if (inturrupt()) {
               return 0;
       }
       
       for (int i = 1; i <= a; ++i) {
               x++;
               if (inturrupt()) {
                      return 0;
               }
               //print();
       }
       for (int i = 1; i <= b; ++i) {
               y++;
               if (inturrupt()) {
                      return 0;
               }
               //print();
       }
       while (c != 0) {
               x--;
               if (inturrupt()) {
                      return 0;
               }
//print();
               for (int i = 1; i <= b - 1; ++i) {
                      y--;
                      if (inturrupt()) {
                              return 0;
                      }
               //     print();
               }
               x--;
               if (inturrupt()) {
                      return 0;
               }
               //print();
               for (int i = 1; i <= b - 1; ++i) {
                      y++;
                      if (inturrupt()) {
                              return 0;
                      }
               //     print();
               }
       }
       return 0;
}

inturrupt 함수는 한번 x나 y를 바꾸는 연산을 한 다음에 실행시켜 줘서 k가 0이 되면 x,y를 출력하고 끝내도록 만들었다. 코드는 엄청 복잡했다. 

#include <iostream>
#include <string>
using namespace std;
int c;
int x = 1, y = 1;
int main(void) {
       int n, m;
       cin >> n >> m >> c;
       if (c < n) {
               cout << 1 + c << ' ' << 1 << endl;
               return 0;
       }
       if (c < n + m - 1) {
               cout << n << ' ' << (c - (n - 1)) + 1 << endl;
               return 0;
       }
       if (n*m - 1 == c) {
               cout << 1 << ' ' << 2 << endl;
               return 0;
       }
       c -= (m + n - 2);
       int temp = n - 1 - ((c-1) / (m - 1));
       int temp2;
       if (temp % 2 == 0) {
               temp2 = 1 + (c-1) % (m - 1);
       }
       else {
               temp2 =  m - 1 - (c-1) % (m - 1);
       }
       cout << temp << ' ' << temp2 + 1 << endl;
       return 0;
}

x와 y를 n,m,k에 대한 식으로 나타내서 짠 코드. 여기서 
Note that k doesn't fit into 32-bit integer type!
이런 문구가 있는 걸 간과했다. long long 으로 작성하면 accept를 받을 수 있었다. 



C. Nested Segments


뻔한 문제 같은데 도저히 풀 방법이 생각나지 않았다. Contest 가 끝나고 나서 코드를 확인해 보니

좌표를 묶어서 first 크기대로 정렬을 한다. first가 같으면 second가 작은 순으로 정렬한다. 

본래 순서의 index를 가지고 있어야 하므로 index배열을 따로 만들고 index배열을 정렬시키면서 정럴시키는 cmp 함수안의 조건은 pair값을 사용한다. 

정렬이 끝나면 첫번째 값은 무조건 다음값에 포함되므로 생각하지 않고 second 값만 비교한다. 

#include <iostream>
#include <algorithm>
using namespace std;
int u[300001];
pair<int, int> in[300001];
int main(void)
{
       int n;
       cin >> n;
       for (int i = 1; i <= n; ++i) {
               u[i] = i;
               cin >> in[i].first >> in[i].second;
       }
       sort(u + 1, u + n + 1, [](int a, int b) {
               if (in[a].first != in[b].first) {
                      return in[a].first < in[b].first;
               }
               else {
                      return in[a].second > in[b].second;
               }
       });
       int temp = u[1];
       for (int i = 2; i <= n; ++i) {
               if (in[temp].second >= in[u[i]].second) {
                      cout << u[i] << ' ' << temp << endl;
                      return 0;
               }
               else {
                      temp = u[i];
               }
       }
       cout << -1 << ' ' << -1 << endl;
       return 0;
}




A. Splits

A 번 문제가 아니었다면 못풀었을 것 같다. 
A라 분명 쉬울껀데 하면서 계속 해보니까 
결국 중요한 건 맨 앞에 오는 숫자의 개수이고 뒤는 1로 다 채워버려도 됐다. 
어떤 숫자가 n이라면

n개를 다 1로 채우는 방법,
n개에서 한개를 2로하고 나머지를 1로 채우는 방법
n개에서 2개를 2로하고 나머지를 1로 채우는 방법

... 

n개에서 n/2개를 2로하고 나머지가 있다면 1로 두는 방법 으로 구할 수 있다.

따라서 모든 방법의 수는 n/2+1

#include <iostream>
using namespace std;
int main(void)
{
       int n;
       cin >> n;
       cout << n / 2 + 1;
       return 0;
}



B. Messages


브루트포스로 풀었다. 

편지를 안 읽고 두냐, 아니면 얼른 읽어버리냐의 최대값의 차이는 

(t-ti)*c + (a-b*(t-ti))

이런 수식으로 구할 수 있었다. ti를 편지를 받은 tb[i] 부터 끝까지 가지고 있는 <= t 로 범위를 준 후 다 해본다음의 max 값을 ans 에 더해줘서 구했다. 

이게 될까 싶었는데 돌려보니 바로 Accept 가 떠서 신기했다. 

#include <iostream>
#include <algorithm>
using namespace std;
int tb1[100001];
int main(void)
{
       int n, a, b, c, t;
       cin >> n >> a >> b >> c >> t;
       for (int i = 0; i<n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i<n; ++i) {
              int tmax = 0;
              for (int ti = tb1[i]; ti <= t; ++ti) {
                     int temp = (t - ti)*c + (a - b * (t - ti));
                     tmax = max(tmax, temp);
              }
              ans += tmax;
       }
       cout << ans << endl;
       return 0;
}






한시간 동안 풀었는데 결국 풀지 못했다. 

[2 3 1]

의 뜻이 뭔지 이해가 안 되었던게 컸던 것 같다. 

처음에 생각했던 것은 tetris 니까 n개의 블록을 잘 내려서 줄을 없애라는 줄 알았다. 

이렇게 하면 1개가 있는 자리에 n개의 블록을 1개씩 보내주면 모두 2개 이상이 되어 두 줄을 없앨 수 있어서 

2가 답인 줄 알았다. 

해석할 때 시간이 오래 걸릴 것 같아 파파고번역기로 번역을 해서 한게 좋지 않은 영향을 준 것 같다. 

실제 문제는 Hack 단계에서 다른 사람의 코드를 보니 3개의 열이 있고 주어진 블록을 해당열에다가 쌓는 형식이었다.

문제만 제대로 이해했으면 금방 풀었을 텐데 아쉽다. 

Accept 받은 코드
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
int che[100001];
bool doo[100001];
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < m; ++i) {
              int k;
              cin >> k;
              tb1[k]++;
       }
       int ans = INT32_MAX;
       for (int i = 1; i <= n; ++i) {
              ans = min(ans, tb1[i]);
       }
       cout << ans << endl;
       return 0;
}



B. Lecture Sleep


주인공은 잠이 많아 수업시간에 조는데 깨어있는 동안은 열심히 적는다. 

단 한번 깨울 수 있는데 깨우면 m분만큼 필기를 한다.

 최대한 많이 필기 하는 양을 출력

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
bool che[100001];
bool doo[100001];
stack<int> st;
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i < n; ++i) {
              int k;
              cin >> k;
              che[i] = k;
              if (k == 1) {
                     st.push(i);
                     ans += tb1[i];
              }
       }
       
       int tempansmax = 0;
       for (int i = 0; i < n-m+1; ++i) {
              int tempans = ans;
              for (int k = i; k < i + m; ++k) {
                     if (che[k] == 0) {
                           tempans += tb1[k];
                     }
              }
              tempansmax = max(tempansmax, tempans);
       }
       cout << tempansmax << endl;
       return 0;
}

Time Out 날 걸 확신하고 쓴 코드. 
 for (int k = i; k < i + m; ++k) {
                     if (che[k] == 0) {
                           tempans += tb1[k];
                     }
              }
이 코드를 조금 만 더 최적화 하면 될 것 같다. 

바뀌는 부분은 맨 처음과 맨 끝이므로 
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
bool che[100001];
bool doo[100001];
stack<int> st;
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i < n; ++i) {
              int k;
              cin >> k;
              che[i] = k;
              if (k == 1) {
                     st.push(i);
                     ans += tb1[i];
              }
       }
       int tempans = ans;
       int tempansmax = 0;
       for (int k = 0; k < m; ++k) {
              if (che[k] == 0) {
                     tempans += tb1[k];
              }
       }
       for (int i = 1; i < n-m+1; ++i) {
              if (che[i - 1] == 0) {
                     tempans -= tb1[i - 1];
              }
              if (che[i + m - 1] == 0) {
                     tempans += tb1[i + m - 1];
              }
              tempansmax = max(tempansmax, tempans);
       }
       cout << tempansmax << endl;
       return 0;
}
이렇게 수정을 했는데 TC4에서 Wrong answer 이 나왔다. 

int tempans = ans;
       int tempansmax = 0;
       for (int k = 0; k < m; ++k) {
              if (che[k] == 0) {
                     tempans += tb1[k];
              }
       }
       for (int i = 1; i < n-m+1; ++i) {
              if (che[i - 1] == 0) {
                     tempans -= tb1[i - 1];
              }
              if (che[i + m - 1] == 0) {
                     tempans += tb1[i + m - 1];
              }
              tempansmax = max(tempansmax, tempans);
       }

여기서 tempansmax가 for(int i=1 로 들어가기 전에 k=0~m 까지 더한 값을 저장하고 가야 하는데 놔두고 가서 TC4가
k=0에서 시작해서 하는게 최대값인 경우라 Wrong Answer 이었다 보다


Accept 받은 코드
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
int che[100001];
bool doo[100001];
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i < n; ++i) {
              int k;
              cin >> k;
              che[i] = k;
              if (k == 1) {
                     ans += tb1[i];
              }
       }
       int tempans = ans;
       
       for (int k = 0; k < m; ++k) {
              if (che[k] == 0) {
                     tempans += tb1[k];
              }
       }
       int tempansmax = tempans;
       for (int i = 1; i < n-m+1; ++i) {
              if (che[i - 1] == 0) {
                     tempans -= tb1[i - 1];
              }
              if (che[i + m-1] == 0) {
                     tempans += tb1[i + m-1];
              }
              tempansmax = max(tempansmax, tempans);
       }
       cout << tempansmax << endl;
       return 0;
}


+ Recent posts