스택을 다룰때 자주 실수하는 것
st.top() 을 접근하기 전에, !st.empty()  스택이 비어있지 않은지 확인해야 한다.
 
#include <bits/stdc++.h>
using namespace std;

int n, answer;
string word;

bool check(string input){
  stack<char> st;

  int slen = input.length();
  if (slen % 2 == 1) return false;

  st.push(input[0]);
  for(int i = 1; i < slen; i++){
    if(!st.empty() && st.top() == input[i]) st.pop();
    else st.push(input[i]);
  }
  if(st.empty()) return true;
  else return false;
}

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

  cin >> n;
  while(n--){
    cin >> word;
    if (check(word)) answer++;
  }
  cout << answer;
  return 0;
}
 
짝이 맞으려면 문자열 길이가 일단 짝수여야 한다. 
 
문자열을 길이만큼 인덱스로 순회한다. 
스택의 제일 위의 top 글자가 현재 인덱스 글자와 같으면, top을 pop시킨다. 
현재 인덱스 글자 와 다르면, 현재 인덱스 글자를 push한다. 
 
순회가 끝났을 때 스택이 비어있어야 좋은 단어다. 
728x90

'알고리즘 > 백준' 카테고리의 다른 글

쇠막대기 백준 10799번 c++  (0) 2022.02.13
괄호 백준 9012번 c++  (0) 2022.02.13
Hasing 백준 15829번 c++  (0) 2022.02.11
시리얼 번호 백준 1431번 c++  (0) 2022.02.10
곱셈 백준 1629번 c++  (0) 2022.02.09
 
 
모듈러 연산의 성질을 이용한 문제다. 
 (a * b ) mod n == (a mod n) * (b mod n)
 
#include <bits/stdc++.h>
using namespace std;

long long MOD = 1234567891;
long long MUL = 31;
int L;
string input;

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

  cin >> L >> input;

  long long answer = 0; // 합 누적
  long long R = 1; // 제곱근 처음에 1로 시작

  for(int i = 0; i < L; i++){
    // input[i] - 'a' + 1 : 문자의 인덱스. a는 1이 나오도록.
    long long idx = input[i] - 'a' + 1;
    answer = (answer + (idx * R)) % MOD;
    R = (R * MUL) % MOD; // 곱할 숫자
  }
  // 마지막에 항상 % MOD를 해서 숫자가 커지는 것을 방지한다
  cout << answer;

  return 0;
}
 

 

728x90

'알고리즘 > 백준' 카테고리의 다른 글

괄호 백준 9012번 c++  (0) 2022.02.13
좋은 단어 백준 3986번 c++ (두번째 풀기)  (0) 2022.02.11
시리얼 번호 백준 1431번 c++  (0) 2022.02.10
곱셈 백준 1629번 c++  (0) 2022.02.09
큰 수 A+B 백준 10757번 c++  (0) 2022.02.09
예전에 틀렸던 부분 그대로 다시 틀렸다 ... 
 
#include <bits/stdc++.h>
using namespace std;

int n; // 기타 개수
string st;
vector<string> v;

int digit_sum(string &a){ // 문자열 중에 숫자만 뽑아서 합을 리턴
  int sum = 0;
  for(auto num : a) {
    if(isdigit(num)) sum += (num - '0');
  }
  return sum;
}

bool check(string &a, string &b){

  int alen = a.size(), blen = b.size(); // 문자열 길이 
  int asum = digit_sum(a), bsum = digit_sum(b); // 숫자합 

  // 길이가 다르면 길이끼리 비교
  if(alen != blen) return alen < blen;
  // 합이 다르면 합끼리 비교
  if(asum != bsum) return asum < bsum;
  // 사전순
  return a < b;
}

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

  cin >> n;

  while(n--){
    cin >> st;
    v.push_back(st);
  }
  sort(v.begin(), v.end(), check); // 비교함수로 정렬 
  for(auto s : v) cout << s << '\n';

  return 0;
}
 
문제의 정렬 조건은 3가지다. 
 
첫 째, 문자열 길이 →  size() 를 구해 비교
둘 째, 숫자 합 크기 → 문자를 isdigit() 으로 숫자인지 판별. 리턴은 bool
셋 째, 사전순 → a < b 아스키코드 오름차순이라서 간단.
 

아래는 틀린코드다.
bool check(string &a, string &b){

  int alen = a.size(), blen = b.size();

  if(alen < blen) return alen < blen;
  else if(alen == blen){ // 각각 숫자만 뽑아서 합 비교 
    int asum = 0, bsum = 0;
    for(int i = 0; i < alen; i++){ // 길이가 같으니까 인덱스 똑같이 사용 
      if(isdigit(a[i])) asum += (a[i] - '0');
      if(isdigit(b[i])) bsum += (b[i] - '0');
    }
    return asum < bsum;
  }else{ // 사전순
    return a < b;
  }
}
 
틀린 원인
길이 비교라는게, 길이가 달라야 비교하는 것이다. 
아래 처럼 <  로 조건을 넣으니까 틀렸다. 
[X] if(alen < blen) 
[O] if(alen != blen) 
 
숫자 합 비교도 마찬가지다. “달라야"비교한다. 
[X] if(asum < bsum) 
[O] if(asum != bsum) 
 
728x90

'알고리즘 > 백준' 카테고리의 다른 글

좋은 단어 백준 3986번 c++ (두번째 풀기)  (0) 2022.02.11
Hasing 백준 15829번 c++  (0) 2022.02.11
곱셈 백준 1629번 c++  (0) 2022.02.09
큰 수 A+B 백준 10757번 c++  (0) 2022.02.09
피보나치 수 4 백준 10826번 c++  (0) 2022.02.08
 
a의 b승을 계산해서 c로 나눈 나머지를 구해야 하는 문제다. 어려웠다. 
검색해보니까 분할정복으로 풀어야 하는 문제다. 

분할정복으로 a의 b승 구현하기 

a제곱 b는 아래와 같이 구현할 수 있다. 
int pow(int a, int b){
 if(b == 0) return 1; 
 if(b == 1) return a;
 if(b%2 == 0) { // 짝수 승이라면, 
  int temp = pow(a, b/2);
  return temp*temp;
 }
 return pow(a, b-1); // 홀수 승이면 1승 차이.
}
 
 
pow(a, b)함수로 2의 4승을 연산하려면 pow(2, 4)다. 
 
2의 0 승인 경우, 0승은 항상 1이다.
2의 1승인 경우, 1승은 항상 2이다. 
 
여기서 중요한 건, b가 짝수인 경우다. 
2의 4승 == ( 2의 2승 * 2의 2승 )
따라서 b가 짝수라면, b/2승 결과를 구해서 temp에 저장하고, temp를 제곱하면 된다. 

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

ll a, b, c;

ll rec(ll a, ll b){
  if(b == 0) return 1;
  if(b == 1) return a % c;

  long long temp = rec(a, b/2);
  if(b%2 == 0){ // b가 짝수라면,
    return (temp * temp) % c; // b/2승을 제곱하면 된다.
  }
  else{// b가 홀수라면, 1번 더 a를 곱해준다.
    return ((temp * temp) % c) * a % c;
  }
}

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

  cin >> a >> b >> c;
  cout << rec(a, b);
  return 0;
}
 
’나머지 구하기'를 제쳐두고 a의 b승을 하면, 숫자가 너무 커져서 long long 으로 연산이 불가능하다. 
 
따라서 ‘a를 c로 나눈 나머지'만 기억하면서 연산해야 한다. 
예를 들어, a의 1승은 a % c 가 되어야 한다. 
a의 2승은 (a % c) * (a % c) 가 되어야 한다. 
 
2의 4승 == ( 2의 2승 * 2의 2승 ) 임을 이용해서 분할정복으로 구현했다. 
 
짝수 b승을 계산할 때, 
b/2 승 * b/2 승을 연산하되, 마지막에는 반드시 c로 나눈 나머지를 저장하자. 
 

 

728x90

'알고리즘 > 백준' 카테고리의 다른 글

Hasing 백준 15829번 c++  (0) 2022.02.11
시리얼 번호 백준 1431번 c++  (0) 2022.02.10
큰 수 A+B 백준 10757번 c++  (0) 2022.02.09
피보나치 수 4 백준 10826번 c++  (0) 2022.02.08
피보나치 수 5 백준 10870번 c++  (0) 2022.02.08
 
long long, unsigned long long 으로도 못 담는 긴 숫자들이라 string 에 숫자들을 저장했다. 
연산하려면 자리수마다 숫자를 더해줘야 하니까, string을 vector<int>로 모두 변환했다. 
 
숫자 자리수가 다르더라도, 덧셈을 할 때는  두 숫자의 1의  자리 부터 하니까. 두 숫자의 길이가 맞아야 한다. 
짧은 숫자 vector에 0을 먼저 넣어둬서 a_vec과 b_vec의 길이를 맞춘다. 
 
vector의 맨 뒤가 1의 자리니까. 뒤에서부터 연산을 한다. 1의자리, 10의 자리, 100의 자리... 순이다. 
연산 결과는 answer 문자열에 한 자리 숫자를 붙인다. (숫자에 ‘0’을 더하면 문자 ‘0’이 된다. )
답 출력 직전에 answer 문자열을 뒤집으면, 정상 숫자로 출력할 수 있다. 
 
올림수 처리가 중요하다. 
예를 들어, 7 + 5 = 12 가 되니까. 올림수가 발생한다. 
carry 가 생기면, 1의 값을 갖게 했다. 그래서 다음 연산때 1을 더해주고, carry를 다시 0으로 돌려놓는다. 
 
#include <bits/stdc++.h>
using namespace std;

string a, b, answer;
vector<int> a_vec, b_vec;
int carry, temp_sum; // 올림수, 한 자리수 더함.

// 숫자 + '0' == 문자 
// 문자 - '0' == 숫자
int main(void){
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> a >> b;

  if(a.size() < b.size()) swap(a, b);
  int diff_len = a.size() - b.size();

  // a, b 문자열의 문자를 하나씩 int 벡터로 넣는다.
  for(int i = 0; i < a.size() ; i++) a_vec.push_back(a[i]-'0');
  for(int i = 0; i < diff_len; i++) b_vec.push_back(0);
  for(int i = 0; i < b.size(); i++) b_vec.push_back(b[i]-'0');

  for(int i = a_vec.size()-1; i >= 0 ; i--){ // 뒤 부터 앞으로
    temp_sum = a_vec[i] + b_vec[i];

    if(carry == 1){ // 이전에 올림수가 있었다면, 1 더한다.
      temp_sum++;
      carry = 0;
    }
    if(temp_sum > 9){ 
      temp_sum %= 10;
      carry = 1; // 올림수 발생했으니까 1로 변경.
    }
    answer += (temp_sum + '0'); // 숫자를 문자열에 이어붙인다 
  }
  if(carry == 1) answer += '1'; // 올림수가 있다면, 1을 덧붙임
  reverse(answer.begin(), answer.end()); // 문자를 뒤집기 
  cout << answer;
  return 0;
}
 

참고 
728x90

'알고리즘 > 백준' 카테고리의 다른 글

시리얼 번호 백준 1431번 c++  (0) 2022.02.10
곱셈 백준 1629번 c++  (0) 2022.02.09
피보나치 수 4 백준 10826번 c++  (0) 2022.02.08
피보나치 수 5 백준 10870번 c++  (0) 2022.02.08
피보나치 수 백준 2747번 c++  (0) 2022.02.08
 
 
값이 길어져서 unsigned long long 으로도 커버가 안되는 문제다. 
string 끼리의 덧셈으로 풀어야 한다. 올림이 발생하면, 다음 자리수의 덧셈에 올림 수를 더해주는 연산이 필요하다. 
다른 분들의 풀이 포스팅을 읽고 이해했다. 다시 풀어 볼 문제. 
 
 
#include <bits/stdc++.h>
using namespace std;

int n, sum;
string a, b, tmp, fibo[10002];
vector<int> ans, num1, num2;

string big_num_sum(string s1, string s2){

  string s = "";

  // 더 긴 수를 s1에 저장한다.
  if(s1.size() < s2.size()) swap(s1, s2);

  // num1, num2 배열을 만든다.
  num1.push_back(0);
  num2.push_back(0);

  // s1이 더 긴 수니까. 그대로 num1 벡터를 채운다.
  for(int i = 0; i < s1.size(); i++)
    num1.push_back(s1[i] - '0');

  // s2가 비교적 짧은 수니까. s1, s2 길이 차이만큼 0을 num2 벡터에 채운다.
  for(int i = 0; i < s1.size() - s2.size(); i++)
    num2.push_back(0);

  for(int i = 0; i < s2.size(); i++)
    num2.push_back(s2[i] - '0');

  // num1, num2 벡터 맨 뒤부터 앞쪽으로 덧셈을 하면서 ans 벡터에 저장
  for(int i = s1.size(); i > 0; i--){
    sum = num1[i] + num2[i];
    if(sum > 9){
      num1[i-1] += 1; // 올림 수 발생했으니까 1을 더해준다.
      sum -= 10;
    }
    ans.push_back(sum);
  }

  // 맨 앞자리수에 올림수가 넘어왔다면,
  if(num1.front() != 0) s.push_back('1');

  // ans 벡터 원소 순서를 거꾸로.
  reverse(ans.begin(), ans.end());
  // ans 벡터의 숫자를 순차 출력하여 문자열 s에 이어붙인다. 
  for(auto n : ans){
    s.push_back(n+48); // 문자로 저장해야 하니까 48을 더해준다.  
  }
  num1.clear(); num2.clear(); ans.clear();
  return s;
}

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

  cin >> n;

  fibo[0] = "0";
  fibo[1] = "1";

  for(int i = 2; i <= n; i++){
    fibo[i] = big_num_sum(fibo[i-1], fibo[i-2]);
  }
  cout << fibo[n];

  return 0;
}
 
 

다시 푼 코드 링크

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

int input;
string a, b, answer; // 긴 숫자를 문자로 표현
vector<int> va, vb; // 연산을 위한 벡터

string fibo(string &a, string &b){
  string res = "";

  int diff_len = b.size()-a.size(); // 숫자 길이의 차이

  for(int i = 0; i < diff_len; i++) va.push_back(0);
  for(auto str : a) va.push_back(str - '0');
  for(auto str : b) vb.push_back(str - '0');

  int carry = 0;
  for(int i = vb.size()-1; i >= 0; i--){
    int temp_sum = va[i] + vb[i];

    if(carry == 1) { // 올림수가 있었다면, 더해주고. 다시 0 으로 돌려놓음
      temp_sum++;
      carry = 0;
    }
    if(temp_sum > 9){
      temp_sum %= 10;
      carry = 1;
    }
    res += (temp_sum + '0');
  }

  if(carry == 1) res += '1';
  reverse(res.begin(), res.end());
  va.clear(); vb.clear();

  return res;
}
// 숫자 + '0' == 문자
// 문자 - '0' == 숫자
int main(void){
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> input;

  a = "0", b ="1";

  if(input == 0) cout << 0;
  else if(input == 1) cout << 1;
  else{
    for(int i = 2; i <= input; i++){
      answer = fibo(a, b);
      a = b;
      b = answer;
    }
    cout << b;
  }
  return 0;
}
728x90

'알고리즘 > 백준' 카테고리의 다른 글

곱셈 백준 1629번 c++  (0) 2022.02.09
큰 수 A+B 백준 10757번 c++  (0) 2022.02.09
피보나치 수 5 백준 10870번 c++  (0) 2022.02.08
피보나치 수 백준 2747번 c++  (0) 2022.02.08
피보나치 수 3 백준 2749번 c++  (0) 2022.02.08
n 번째 피보나치수를 구하는데, 20이하 번째만 구하면 된다. 
수의 크기가 작아서 재귀함수로 풀어도 가능하고. DP 메모이제이션으로 풀어도 통과한다. 
 
#include <bits/stdc++.h>
using namespace std;

long long D[22];
int n;

long long fibo(int num){
  if (num == 0) return 0;
  if (num == 1) return 1;
  return fibo(num-1) + fibo(num-2);
}

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

  cin >> n;
  cout << fibo(n);
  return 0;
}
 
#include <bits/stdc++.h>
using namespace std;

long long D[22];
int n;

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

  cin >> n;

  D[1] = D[2] = 1;
  for(int i = 3; i <= n; i++){
    D[i] = D[i-1] + D[i-2];
  }

  cout << D[n];
  return 0;
}

 

728x90

'알고리즘 > 백준' 카테고리의 다른 글

큰 수 A+B 백준 10757번 c++  (0) 2022.02.09
피보나치 수 4 백준 10826번 c++  (0) 2022.02.08
피보나치 수 백준 2747번 c++  (0) 2022.02.08
피보나치 수 3 백준 2749번 c++  (0) 2022.02.08
피사노 주기 백준 9471 c++  (0) 2022.02.08

+ Recent posts