코테 스터디 1-10번 문제 풀이
[0] 진약수
진약수 갯수 구하기
- 진약수 : 자기 자신을 뺀 약수들
[1] 최대, 최소값
min, max 값 구할 때 팁
int형의 가장 작은 수 : -214000000
int형의 가장 큰 수: 214000000
1
2
3
4
5
6
7
8
9
10
11
//최소값, 최대값 구하기
for(i=1; i<=n; i++){
cin>>a; //cin : enter 치거나 space로 구분하거나 같음
if(a>max){
max=a;
}
if(a<min){
min=a;
}
}
[2] freopen()
input값들을 txt파일에 미리 저장해놓고 쓰는 법
freopen(”[텍스트파일명.txt]”,”rt”, stdin);
- 복잡한 input값들을 미리 정해놓고 긁어다가 활용할 수 있다
- 파일을 읽어와서 stdin 표준입력에 대한 포인터로 전달한다
[3] cin과 scanf
cin 과 scanf
- cin : enter을 치거나 space로 구분하는 것이랑 같음!
- scanf 도 같음!
= ✨ 한줄로 입력 값들을 쭉 칠 수 있음!
[4] 주민등록번호로 나이 계산
주민 등록 번호로 나이 계산하기
[1] 나이 계산 기본
[뒷자리 첫번째 글자]
- 여자
- 2 : ~1999년생
- 4 : 2000년생 ~
- 남자
- 1 : ~1999년생
- 3 : 2000년생 ~
[2] 아스키코드와 숫자 🔥
주민등록의 경우에는 문자열로 받아서 숫자로 계산해야 한다
- 암기하면 편하다
문자 | 아스키코드 |
---|---|
‘0’ | 48 |
[3] 나이 계산 알고리즘
if
[1] ~1999년생과 [2] 2000년생 ~ 으로 나눈다year
출생 년도를 만든다 (98xxxx → 1998)age
현재 년도 기준 - 출생년도 + 1 을 하여 나이를 구한다
1
2
3
4
5
6
7
8
9
10
11
12
//[1] 나이 계산하기
//1)19xx년생 일때 2)20xx년생 일때로 구분하여 나이를 구한다
//** 아스키코드 48 = '0' **
if(a[7]=='1' || a[7]=='2')
year = 1900 + (a[0]-48)*10 + (a[1]-48);
else
year = 2000 + (a[0]-48)*10 + (a[1]-48);
age = 2022-year+1; //연도 기준 2022
[5] 문자열 관련 1
[1]
문자열 구하는 함수 쓰지 않고 반복문 돌리기
- 문자열 끝에는
‘\0’
: NULL 문자가 들어감 🌟 !- 이를 이용하여 반복문을 돌리자
1
2
3
4
//a[i] != '\0' 의 의미: 문자열의 끝을 알리는 문자 = \0
for(i =0; a[i] != '\0';i++){
}
[2]
문자열 아스키 코드로 숫자 구분하기
48 = ‘0’ ~ 57 = ‘9’
숫자 구하기
‘문자’ - 48
1
2
3
4
//아스키 코드로 0부터 9까지의 숫자 문자
if(a[i] >= 48 && a[i] <= 57)
{
}
[6] 문자열 관련 2
[1]
대문자에서 소문자 구하기
대문자 문자 + 32
[2]
공백 (스페이스 입력)을 포함하여 문자열 읽기
- scanf 나 cin 을 사용하면 공백 (스페이스)를 입력 (엔터처리)하여 값이 들어간다
⇒ gets([주소])
를 사용하면, 공백을 포함하여 한줄 통으로 문자열 값으로 쳐진다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
//영어 단어 복구
// 문자열의 공백을 제거하고, 소문자로 변경시켜 출력하라
//bE au T I fu L => beautiful 로 바꿔서 출력!
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char** argv) {
char a[101], b[101];
int i, pos=0;
//* 중요 함수 ! *
gets(a); //공백, 스페이스 상관없이 한줄 읽어버림
for(i =0; a[i] != '\0'; i++){
if(a[i] != ' '){ //[1] 공백이 아닐 때
if(a[i] >= 65 && a[i] <= 90){
b[pos++] = a[i] + 32;
//아스키코드 상 대문자에서 소문자로 변하기 +32를 하면 소문자로 변함
}
else b[pos++] = a[i];
}
}
b[pos] = '\0';
printf("%s\n",b);
return 0;
}
[7] 스택 안 쓰고, 괄호 검사하기
[1]
괄호 검사하기 스택 안 쓰고 풀기 꼼수!
- 괄호를 if 문으로 각각 여는괄호 +1, 닫는괄호 -1로 설정한다
- 거짓 증상
- 닫는 괄호가 더 많은 경우 위 값의 합이 중간에 음수가 나온다
- 사유 : 닫는 괄호가 제대로 나오면 무조건 0이다
- 반복문으로 다 검사 후 합 값이 음수이다
- 닫는 괄호가 더 많은 경우 위 값의 합이 중간에 음수가 나온다
- 참 증상
- 모두 검사했지만 위 경우들에 해당하지 않는다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
//올바른 괄호
//괄호가 입력되는데, 올바르면 YES, 올바르지 않으면 NO 출력
//여는 괄호가 있는데 닫는 괄호가 없으면 올바르지 않은 것임
// [스택 미사용 방법]
// 괄호 당 1 로 값을 할당하고, 닫는 괄호는 -1 음수로 할당한다 => 최종 값이 0 이 아니면 거짓!
int main(int argc, char** argv) {
char a[101];
int i, cnt = 0;
scanf("%s", &a);
for(i =0; a[i] != '\0'; i++){
if(a[i]=='('){
cnt += 1;
}
else if(a[i]==')'){
cnt -= 1;
}
if(cnt <0) break; //중간에 음수가 나오는 경우는 닫는 괄호가 더 많은 경우이므로 무조건 거짓!
}
if(cnt == 0){
printf("YES\n");
}
else{
printf("NO\n");
}
return 0;
}
[8] 빡센 약수 갯수 구하기
N까지의 모든 수의 약수 갯수를 출력하는 문제
배수를 이용하여 배수부터 검사하는 방법을 사용하자
[1]
정석 (빡센 문제에서 타임리미트) 나오는 약수 구하기
1
2
3
4
5
6
7
8
9
10
11
12
13
//[1] ================
int cnt =0;
//타임리미트 풀이
for(i =1; i<=n; i++){
cnt=0;
for(j=1; j<=i; j++){
if(i%j==0){
cnt++;
}
}
printf("%d ",cnt);
}
[2] 배수 검사로 약수 갯수 구하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
//모두의 약수
//*!! 타임리미트 존재 !!*
//N을 입력하면 1부터 N까지의 모든 수의 약수의 갯수가 출력되게 하라
int cnt[50001]; //n의 크기 제한이 <=50000까지 이므로 50001을 배열 길이로 설정
//전역 변수로 배열을 선언하면 값이 0으로 초기화가 된다 !!***
//지역 변수로 cnt를 할당하게 되면 값들이 0으로 초기화 되지 않아서 이상한 값이 나오고
//50001은 너무 큰 배열이라 스택에 할당하게 되면 값이 제대로 할당되지 않을 수가 있다
int main(int argc, char** argv) {
int n,i,j;
scanf("%i", &n);
//[2] =================
// i가 1일 시 cnt 결과 :
//cnt [1] [1] [1] [1] [1] [1] [1] [1] [1] ... [1]
//배수로 약수를 구하는 풀이
//int cnt[50001];
for(i=1; i<=n; i++){
for(j=i; j<=n; j=j+i){//i의 배수로 약수를 증가시키기
cnt[j]++; //j는 i의 배수 이므로 약수 개수 1 추가됨 !
}
//printf("%d ",cnt[i]);
}
for(i=1; i<=n; i++){
printf("%d ", cnt[i]);
}
return 0;
}
[9] 전역 변수 선언
- 지역 변수 선언을 하면 문제가 틀리는 문제가 있다
- 이유:
- 지역 변수는 선언만으로는 초기화가 안 된다
- ↔ 전역 변수 선언은 선언만으로 배열, 변수 값이 0으로 초기화 된다
- 지역 변수는 스택 영역에서 만들어지며, 이 공간이 충분히 크지 않기 때문에 들어가는 값이 너무 크면 이상한 값이 될 수가 있다 ⇒ 전역변수로 선언하자!
- 지역 변수는 선언만으로는 초기화가 안 된다
1
2
3
4
5
6
7
8
int cnt[50001]; //n의 크기 제한이 <=50000까지 이므로 50001을 배열 길이로 설정
//전역 변수로 배열을 선언하면 값이 0으로 초기화가 된다 !!***
//지역 변수로 cnt를 할당하게 되면 값들이 0으로 초기화 되지 않아서 이상한 값이 나오고
//50001은 너무 큰 배열이라 스택에 할당하게 되면 값이 제대로 할당되지 않을 수가 있다
int main(int argc, char** argv) {
...
}
[10] 자릿수의 구하기
자릿수 구하기
- 어떤수 X를 10으로 나눈 나머지 = 제일 오른쪽 자릿수
- 어떤수 X를 10으로 나눈 몫 = 제일 오른쪽 자릿수를 뺀 수
- 123 / 10 → 12
- 어떤수 X를 계속 10으로 나눠서 0이 나누면 다 나눈 것이다
- 100 → (1) 100/10, (2) 10/10, (3) 1/10 = 0 : 다 나눈 것
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#include <iostream> //자릿수의 합 //N개의 자연수가 입력 되면 각 자연수의 자릿수의 합을 구하고, //그 자릿수의 합이 최대인 자연수를 출력하라 //자연수의 자릿수를 구하는 함수는 int digit_sum(int x) 를 작성하라 //자릿수 구하기 int digit_sum(int x){ int tmp, sum = 0 ; //!!**중요**!! //자릿수 구하기 (제일 오른쪽 자릿수 -> 왼쪽 자릿수를 더해가는 식) while(x>0){ tmp = x%10; // 10으로 나눈 나머지 : 제일 끝자리 수 출력 x /= 10; // = 제일 끝자리를 뺀 수 ... 8ㅅ8 sum += tmp; }