어떤 수 n이 소수인지 판별하려면 n을 2부터 n보다 1작은 수(n-1)까지 차례대로 나누어 떨어지는지 검사하면 됨.
나누어 떨어진다는 의미는 나머지가 0임을 뜻함
5는 2,3,4로 나누었을 때 한 번도 나누어 떨어지지 않았으므로 소수
4는 2로 나누었을 때 나누어 떨어졌으므로 소수가 아님.
변수
input : 소수인지 판별하기 위해 입력 받은 숫자가 저장될 변수
i : input보다 1작은 수가 저장될 변수
j : 2부터 i까지 1씩 증가되는 숫자가 저장될 변수, 즉 i가 5이면 j는 2,3,4,5까지 차례로 변경됨
int main() { int input, i, j; scanf("%d", &input); i = input - 1; j = 2; while (1) { if (j <= i) { if (input % j == 0) { printf("소수 아님."); break; } else { j++; } } else { printf("소수."); break; } } return 0;}
임의의 정수를 입력하여 소수를 판별(나누어 떨어질 때)
알고리즘의 이해
소수를 구하는 또 하나의 알고리즘
소수를 판별하는 숫자 n을 2부터 차례로 나누어서 처음으로 나누어 떨어졌을 때 n과 제수(나눈 수)가 같으면 소수.
이 말은 중간에 한 번도 나누어 떨어진 수가 없었다는 것을 의미.
1과 자기 자신을 약수로 갖는 소수라는 거.
변수
input : 소수인지 판별하기 위해 입력 받은 숫자가 저장될 변수
i : 2부터 A까지 1씩 증가되는 숫자가 저장될 변수
int main() { int input, i; scanf("%d", &input); i = 2; // 제수 while (input % i != 0) i++; if (input == i) // 제수 == 피제수 printf("소수"); else printf("소수 아님"); return 0;}
임의의 정수를 입력 받아 소수인지 판별(제곱근 이용)
알고리즘 이해
어떤 수 n이 소수인지 판별하려면 n을 2부터 n의 제곱근까지의 숫자로 나누어 떨어지는지 검사하면 됨.
제곱근까지의 수 중 한 개의 수에 대해서라도 나누어 떨어지면 소수가 아님
예를 들어 25는 2,3,4,5로 나누었을 때 5로 나누어 떨어지므로 소수가 아님
41은 2,3,4,5,6으로 나누어도 한 번도 나누어 떨어지지 않음. 소수
제수는 1씩 증가, 제곱근 값의 소수 부분은 크기 비교시 의미 없음
소수 판별을 그 수의 제곱근까지만 검사하는 이유는?
예를 들어 25가 소수인지 알아 볼 때 25의 제곱근은 5, 2~5까지 나누어 보면됨
즉, 25는 2x12.5 / 3x8.3 / 4x6.25 / 5x5 ...
5 이상의 숫자들로 나누면 5이하의 몫이 나오므로 위에서 실행한 계산이 반복됨.
때문에 5보다 큰 숫자로는 나눌 필요 없음
변수
input : 소수인지 판별하기 위해 입력 받은 숫자가 저장될 변수
i : input를 나누는 제수가 저장될 변수, 즉 i는 2부터 A의 제곱근까지 차례로 변경됨
#include<math.h>int main() { int input, i; scanf("%d", &input); i = 2; // 제수 while(1) { if (i <= sqrt(input)) { // 제수가 제곱근보다 작은 동안에 나눠 떨어지면 소수아님 if (input % i == 0) { printf("소수 아님."); break; } else { i++; } } else { // 위에서 안 나눠 떨어지고 제수가 제곱근보다 크면 소수 printf("소수."); break; } } return 0;}
임의의 정수를 입력 받아 그 안에 포함된 소수의 합을 구하시오. (소수의 합 구하기)
예를 들어 10을 입력 받았다면 2~10 사이에 속한 소수의 합을 계산.
알고리즘의 이해
입력 받은 숫자 n의 범위에 속하는 모든 소수의 합계를 구하려면, 숫자를 2에서 n까지 증가시키면서 각각의 숫자가 소수인지 판별한 후, 그 수가 소수일 때만 합계에 누적하면 됨.
변수
input : 소수를 구할 숫자 범위의 한계를 입력 받아 저장할 변수
sum : 소수가 누적될 변수
i : 소수인지 판별할 숫자가 저장될 변수. input으로 10을 입력 받았다면 K는 2~10까지 차례로 변경됨
j : 소수인지 판별할 때 사용할 제수가 저장될 변수
int main() { int input, sum, i, j; scanf("%d", &input); // 소수를 구할 숫자의 범위를 입력 받음. sum = 0; i = 2; // 소수인지 판별할 숫자가 저장될 변수 while(1) { j = 2; // 제수 while (i % j != 0) j++; if (i == j) // 나눠 떨어졌는데 제수와 피제수가 같다면(소수) sum += i; if (i < input) // 입력받은 a 보다 작으면 피제수를 키워서 반복 i++; else { printf("%d", sum); break; } } return 0;}
배열 A[99]에 2~100 사이의 정수를 기억시킨 후 이 배열을 이용하여 소수의 개수를 구하시오. (소수의 개수 구하기)
알고리즘의 이해
배열에 들어 있는 연속된 숫자의 소수 여부를 판별하기 위해서는 정수의 수열에서 처음 나온 소수의 배수들은 소수가 아니라는 원리를 이용.
배열의 첫 번째에 들어 있는 2는 소수지만 2의 배수들은 모두 소수가 아님.
그러므로 2의 배수가 들어 있는 위치에는 모두 0을 채워 소수가 아님을 표시.
소수의 판별은 배열의 해당 위치에 0이 들어 있는지만 확인하면 됨!
변수
a[99] : 소수 여부를 판별할 숫자가 저장될 배열
k : 2부터 1씩 증가하는 값이 저장될 변수, 즉 K느 2,3,4,...,100까지 차례로 변경됨
i : 배열의 위치를 지정해주는 변수
j : 소수의 개수가 저장될 변수
m : 소수의 배수가 들어있는 위치를 지정할 변수
int main() { int k, i, j, m; int a[99]; k = 1; do { k++; a[k - 2] = k; } while(k < 100); // 2~ 100까지 값을 배열에 할당 i = -1, j = 0; // 배열 a의 첨자 i는 i++을 수행한 후 0이 되도록 -1로 초기화 // j는 소수의 개수를 담을 변수 while (1) { i++; if (i > 98) { // a[98](=100)을 넘으면 출력 printf("%d", j); // 소수의 개수 출력 break; } if (a[i] == 0) { // 값이 0이란 의미는 소수가 아니란 뜻이므로. continue; } j++; // 소수+1 m = i; // 소수를 구한 현재 배열의 위치 i를 그 소수에 대한 배수가 들어 있는 위치를 계산하기 위해 m에게 줌 while (1) { m += a[i]; // 현재 배열의 위치(m)에 이번에 찾은 소수(a[i])를 더해주면 그 소수의 배수가 들어있는 위치가 계산됨. if (m > 99) break; a[m] = 0; // 소수의 배수가 들어있는 위치에 0을 기억시켜 소수가 아님을 표시 } } return 0;}
두 수를 입력 받아 두 수의 최대공약수와 최소공배수를 계산해서 출력하시오.
(최대공약수, 최소공배수)
알고리즘의 이해
최대공약수 - 공통으로 가지고 있는 약수 중 가장 큰 수
최소공배수 - 두 수의 공통인 배수 중 가장 작은 수
최대공약수와 최소공배수를 구할 두 수 중 큰 수와 작은 수를 정한 뒤 큰 수를 작은 수로 나누어 나머지를 구한다.
이 때 나머지가 0이면 그 때의 작은 수가 최대공약수이고, 원래의 두 수를 곱한 값을 최대공약수로 나눈 값이 최소공배수이다.
만약 큰 수를 작은 수로 나누었을 때 나머지각 0이 아니면, 그 때의 작은 수를 큰 수로 하고 나머지를 작은 수로 하여 나머지가 0이 될 때까지 반복.
이와 같이 큰 수를 작은 수로 나눠 나머지가 0이 될 떄까지 반복하여 최대공약수를 구하는 방법을 <b>유클리드 호제법</b>이라 함.
변수
a : 최대공약수와 최소공배수를 구하기 위해 입력 받은 첫 번째 수가 저장될 변수
b : 최대공약수와 최소공배수를 구하기 위해 입력 받은 두 번째 수가 저장될 변수
big : 입력 받은 수 중 큰 수가 저장될 변수
small : 입력 받은 수 중 작은 수가 저장될 변수
mok : 큰 수를 작은 수로 나눈 몫이 저장될 변수
nmg : 큰 수를 작은 수로 나누었을 때 나머지가 저장될 변수
gcd(Greatest Common Divisor) : 최대공약수가 저장될 변수
lcm(Least Common multiple) : 최소공배수가 저장될 변수
INT()로 나머지 구하기
15/12의 나머지 3 구하기
15를 12로 나눠 정수를 취하면 1
몫을 제수와 곱한 후 피제수에서 빼면 나머지를 구할 수 있음
15 - (1x12) -> 3
int main() { int a, b, big, small, mok, nmg, gcd, lcm; scanf("%d %d", &a, &b); if (a >= b) { // 입력 받은 a, b 중 큰 수를 big에 작은 수를 samll에 할당 big = a; small = b; } else { big = b; small = a; } while (1) { mok = big / small; nmg = big - mok * small; // 나머지 = 큰수 - (몫*작은수) if (nmg == 0) { // 나머지가 0 일 때, gcd = small; // 작은수가 gcd(최대공약수) lcm = a * b / gcd; // lcm(최소공배수)는 첫큰수*첫작은수/gcd printf("%d %d", gcd, lcm); break; } big = small; // 나머지가 0이 아니면 작은수를 큰수로 small = nmg; // 나머지를 작은 수로해서 반복 } return 0;}
정수를 입력 받아 약수를 구해 출력(약수 구하기)
알고리즘의 이해
약수 - 어떤 수를 나누어 나머지가 없게 할 수 있는 수.
즉, 나머지가 0이라는 의미. 예를들어 10의 약수는 1, 2, 5, 10.
어떤 수 n을 1부터 n까지 차례대로 나누어 나머지가 0이되게 하는 제수들이 n의 약수.
변수
divisor[100] : 구한 약수가 저장될 1차원 배열
input : 약수를 구하기 위해 입력 받은 숫자가 저장될 변수
c : 1씩 증가되는 제수가 저장될 변수. 즉 c는 1부터 b까지 차례로 변경됨
d : 약수가 저장될 divisor배열의 위치를 지정해 주는 변수. 즉 D는 1부터 약수의 개수까지 차례로 변경됨
mok : 나머지를 구하기 위해 입력 받은 수 b를 c로 나눈 몫이 저장될 변수
nmg : 입력 받은 숫자 b를 c로 나눈 나머지가 저장될 변수
i : 약수를 출력할 때 배열의 위치를 지정해 주는 변수
int main() { int input, mok, nmg, i; int divisor[100]; // 약수를 저장할 배열 scanf("%d", &input); // 약수를 구할 숫자를 input에 입력받음. int c = 0, d = -1; // c는 제수 d는 약수 배열 인덱스 while (1) { c++; if (c <= input) { // 입력받은 input까지 제수로 나눴을 때 나머지가 0인 약수를 구함 mok = input / c; nmg = input - mok * c; if (nmg == 0) { d++; divisor[d] = c; } } else { printf("%d ", input); for (i = 0; i <= d; i++) { printf("%d ", divisor[i]); } break; } } return 0;}
정수를 입력 받아 소인수를 구해 출력(소인수 분해)
알고리즘의 이해
소인수 - 어떤 수를 구성하는 인수 중에서 소수인 것.
어떤 수의 약수중에서 소수인 녀석들만 가리켜서 소인수라 칭함!
소인수 분해 - 소수를 이용하여 그 수를 만드는 곱의 형태로 표현하는 것.
예를 들어 20의 약수는 1, 2, 4, 5, 10, 20 이지만 1, 4, 10, 20은 소수가 아님.
소인수를 구했으면 그 때의 몫을 n로 하여 2부터 다시 n의 제곱근까지의 숫자로 나누는 작업을 반복
만약 제수가 n의 제곱근보다 커지면 그때는 몫인 n자체가 그 수의 소인수가 된다.
변수
p[100] : 소인수가 저장될 배열
n : 소인수로 분해하기위해 입력 받은 숫자가 저장 될 변수
pIndex : 소인수로 저장할 배열 p의 위치를 지정해 주는 변수
d : 제수가 저장될 변수. 2부터 입력 받은 수 B의 제곱근까지 1씩 증가하는 숫자가 저장됨
e : 입력 받은 수 n의 제곱근이 저장될 변수, 즉 n가 20이면 e에는 4가 저장됨
mok : n을 d로 나눈 몫이 저장될 변수
nmg : n을 d로 나눈 나머지가 저장될 변수
int main() { int n, pIndex, d, e, mok, nmg; int p[100]; scanf("%d", &n); // 정수 n을 입력받아서 소인수 구해 출력 pIndex = -1; // 소인수를 저장할 배열의 인덱스 d = 2; // 제수 while (1) { e = (int)sqrt(n); // 입력 받은 값 n의 제곱근(e)을 구해 정수로 변환 while (1) { if (d > e) { // 제수가 n의 제곱근(e)보다 커지면 d = n; // 피제수(n) 자체가 소인수 break; } mok = n / d; nmg = n - mok*d; if (nmg == 0) // 처음으로 나머지가 0이 되게 하는 수가 그 수의 소인수. break; else d++; // d를 2부터 b의 제곱근(e)까지 증가 시키기 위해 1을 더함. } pIndex++; // pIndex늘리고 p[pIndex] = d; // 소인수를 저장하는 배열p[]에 제수 저장 if (n == d) // 제수가 입력값과 같으면 소인수분해 과정을 모두 마친 것. break; // 소인수를 구하고 분해과정이 모두 안끝났다면(n != d) n = mok; // 그 때의 mok을 n로 하여 반복 } for (int i = 0; i <= pIndex; i++) { // 소인수 출력 printf("%d ", p[i]); } return 0;}
10진수를 입력 받아 2진수로 변환하시오. 단, 1000이하의 숫자를 입력 받음.
(진법변환 - 10진수를 2진수로 변환)
알고리즘의 이해
10진수를 2진수로 변환하려면 10진수를 2로 나누어 나머지를 구한 후 저장,
다시 몫을 2로 나누어 나머지를 구해 저장하는 과정을 반복.
몫이 0이 될 때까지 이 작업을 반복
마지막에 구한 나머지부터 거꾸로 출력.
1000이하의 숫자는 2진수로 변환할 때 10개의 요소를 갖는 배열이면 충분
변수
b[10] : 입력 받은 10진수를 2로 나눈 나머지(2진수)가 저장될 배열
decimal : 입력 받은 10진수가 저장될 변수
decimal_copy : 입력 받은 10진수를 그대로 출력하기 위해 b가 저장될 변수
bIndex : 배열의 위치를 지정해주는 변수
mok : b를 2로 나눈 몫이 저장될 변수
nmg : b를 2로 나눈 나머지가 저장될 변수
i : 배열을 출력할 때 배열의 위치를 지정해 주는 변수
int main() { int decimal, decimal_copy, bIndex, mok, nmg, i; int b[10]; scanf("%d", &decimal); decimal_copy = decimal; // 원래 입력값을 나중에 출력하기 위해 복사 // c언어는 배열이 0부터 시작, bIndex++를 수행하고 0이되도록 -1로 초기화. bIndex = -1; do { bIndex++; mok = decimal / 2; nmg = decimal - mok*2; b[bIndex] = nmg; // 2로 나눈 나머지를 b배열에 저장 decimal = mok; // 몫을 10진수로 하여 2로 못 나눌 떄까지 반복 } while (mok != 0); printf("%d ", decimal_copy); // 원래 입력값 출력 // 배열의 위치가 0 부터 시작하기 때문에 // 첨자 i는 2진수가 저장된 마지막 위치인 bIndex부터 0이 될때까지 반복 수행 for (i = bIndex; i >= 0; i—) printf("%d", b[i]); return 0;}
배열의 끝 쪽부터 저장하기
2로 나눈 나머지를 배열의 끝 쪽부터 저장하면 출력할 때 앞에서부터 차례로 출력 가능
2진수를 뒷자리부터 구하지만 출력할 떄는 앞자리부터 출력한다는 것과 배열에서 2진수가 들어 있는 첫 번째 위치를 계산하는 것이 이 알고리즘의 핵심
변수 k 추가
k : 맨 처음 출력할 배열의 위치를 지정해 주는 변수
...int k;... do { bIndex++; mok = decimal / 2; nmg = decimal - mok*2; b[9 - bIndex] = nmg; // 배열의 뒤쪽에서부터 차례로 저장되도록 처리 decimal = mok; } while (mok != 0); printf("%d ", decimal_copy); k = 9 - bIndex; // 2진수가 들어 있는 첫 번째 위치를 계산. for (i = k; i < 10; i++) printf("%d", b[i]);...