백준 1010번을 풀이 방법들을 찾아보던 중, 어떤 블로그에 나와 있는 풀이를 보았는데,
오버플로우를 고려하지 않고 30!을 그대로 계산하는 것이였다.
뭔가 이상했다. 30!을 팩토리얼 계산기로 계산해보니
팩토리얼 계산기로 계산을 해보니, 30!은 10^30이 넘어가는 숫자다.
근데 10은 2x2x2보다 더 큰 수고, 즉 10의 30승은 2의 90승보다 더 큰 수라는것,
컴퓨터에서는 2진법을 사용하기 때문에 30!은 90자리가 넘어간다는 것
자바에서의 long은 64비트, C/C++에서 long long이 64비트이므로
64비트 정수형을 사용해도 30!을 계산하면 이미 오버플로우가 발생한다.
그래서 분명히 문제가 생겨야 하는데 해당 블로그에서 사용한 풀이는 문제가 없던 것이었다.
궁금해서 구글링을 해봤다. 파이썬에서는 수 제한이 없다고 한다
링크를 참고 하면,
파이썬에서는 숫자가 계속 늘어나면 자동으로 해당 수에 사용할
메모리를 확장해서 사용한다고 한다.
def f(n):
ans = 1
for i in range(1,n+1):
ans *= i
return ans
t = int(input())
for i in range(t):
s = input().split(" ")
r = int(s[0])
n = int(s[1])
print(f(n)//(f(r)*f(n-r)))
이 방법 말고도 자바에서 BigInteger을 이용하게 된다면
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.StringTokenizer;
public class Main{
private static BigInteger f(int n){
BigInteger ans = new BigInteger("1");
for (int i = 1; i <= n; i++) {
ans = ans.multiply(new BigInteger(Integer.toString(i)));
}
return ans;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int testCount = Integer.parseInt(br.readLine());
for (int i = 0; i < testCount; i++) {
StringTokenizer stk = new StringTokenizer(br.readLine());
int r = Integer.parseInt(stk.nextToken());
int n = Integer.parseInt(stk.nextToken());
System.out.println(f(n).divide(f(r).multiply(f(n-r))));
}
}
}
이와 같은 방법으로도 해결할 수 있었다