[BOJ][C++] 11401번 이항 계수 3

2024. 10. 26. 01:22·PS/백준 문제

안녕하세요.
오늘은 백준 11401번: 이항 계수 3(링크)  문제를 풀어보려고 합니다.
 

문제

자연수 N과 정수 K 가 주어졌을 때 이항 계수 (N, K)를 1,000,000,007로 나눈 나머지를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 4,000,000, 0 ≤ K ≤ N)

 

출력

(N, K)를 1,000,000,007로 나눈 나머지를 출력한다.

 

예제 입력

5 2

 

예제 출력

10

 

제한
시간 제한: 1초
메모리 제한: 256MB
 


풀이

페르마의 소정리와 모듈러 곱셈 역원을 사용하면 쉽게 풀리는 문제였다.
 

우리가 구하려는 것은 (N, K) % m이다. 그리고 이항 계수의 정의에 따라 이는 아래와 같이 쓸 수 있다.

 
그런데 분수에서는 모듈러 연산이 그대로 적용이 안되는 문제가 발생한다.
이때, 페르마 소정리와 모듈러 곱셈 역원을 사용하면 해결할 수 있다.
 

먼저 페르마의 소정리는 아래와 같다.

 
위 사진에서 아래 식은 아래와 같이 모듈러 곱셈 역원을 통해 표현 가능하다.

 
우리가 어떤 분수 A/B를 p로 나눈 나머지를 구하고 싶다면, 이는 AB^-1 % p로 다시 쓸 수 있다.
즉, 이항 계수를 m으로 나눈 나머지를 구할 때 우리는 다음과 같이 계산할 수 있다.
 

 
 
우리가 나누려는 수 1,000,000,007은 소수이므로 위 식을 그대로 적용할 수 있다.
 
여기서 (k!(n-k)!)^(p-2)를 구할 때 분할 정복을 이용한 거듭제곱을 사용해서 계산해 주면 된다.
 

정답

더보기
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
using ll = long long;
ll m = 1000000007;

ll pow(ll n, ll k) {
	if (k == 0) return 1;
	if (k == 1) return n%m;
	ll tmp = pow(n, k / 2) % m;
	if (k % 2 == 0) return (tmp%m * tmp%m) % m;
	else return ((tmp%m * tmp%m) * n % m) % m;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cin.tie(NULL);
	ll n, k; cin >> n >> k;
	//B^(P-2) === B^-1 (mod P)
	//AB^-1%P = AB^(P-2)%P = (A%P) * (B^(P-2)%P) % P
	ll A = 1;
	for (int i = 1; i <= n; i++) A = (A * i) % m;
	ll B = 1;
	for (int i = 1; i <= k; i++) B = (B * i) % m;
	ll BB = 1;
	for (int i = 1; i <= n - k; i++) BB = (BB * i) % m;
	B = (B % m * BB % m) % m;
	B = pow(B, m - 2) % m;
	cout << (A%m * B%m) % m;
}

이렇게 해서 백준  11401번 이항 계수 3 문제를 풀어보았습니다.
 
댓글로 질문을 남기시면 성실히 답해드리겠습니다
 
감사합니다!
 
참고

더보기

https://blog.naver.com/hongjg3229/221650178981

[백준 11401] 이항 계수3 - 페르마의 소정리, modular inverse

https://www.acmicpc.net/problem/11401 이 문제 덕분에 페르마의 소정리, 합동식에 이항계수까지 한번 정...

blog.naver.com

 

저작자표시 변경금지 (새창열림)

'PS > 백준 문제' 카테고리의 다른 글

[BOJ][C++] 3051번 오아시스 재결합  (3) 2024.10.28
[BOJ][C++] 1562번 계단 수  (0) 2024.10.26
[BOJ][C++] 2342번 Dance Dance Revolution  (1) 2024.10.16
[BOJ][C++] 11444번 피보나치 수 6  (0) 2024.10.14
[BOJ][C++] 10830번 행렬 제곱  (0) 2024.10.14
'PS/백준 문제' 카테고리의 다른 글
  • [BOJ][C++] 3051번 오아시스 재결합
  • [BOJ][C++] 1562번 계단 수
  • [BOJ][C++] 2342번 Dance Dance Revolution
  • [BOJ][C++] 11444번 피보나치 수 6
깜냥c
깜냥c
게임 개발/클라이언트/AI/PS/기타 연구
  • 깜냥c
    Choice Program
    깜냥c
  • 전체
    오늘
    어제
    • 분류 전체보기 (56)
      • 언어 (11)
        • C,C++ (9)
        • C# (1)
        • Python (1)
      • PS (20)
        • 백준 문제 (19)
        • 알고리즘 (1)
      • 인공지능 (2)
      • 게임제작 (7)
      • 게임개발 (13)
        • Unity (6)
        • Unreal Engine (5)
        • Godot Engine (1)
      • 기타 (2)
  • 블로그 메뉴

    • 홈
    • 방명록
    • 블로그 소개
  • 링크

    • 김병장의 IT 블로그
    • 식품영양과 데이터사이언스
  • 공지사항

  • 인기 글

  • 태그

    백준
    C언어
    배낭 문제
    입출력
    Unreal
    BOJ
    unity
    C++
    Godot
    UE5
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
깜냥c
[BOJ][C++] 11401번 이항 계수 3
상단으로

티스토리툴바