포스트

Softeer Lv2. 바이러스

Softeer.ai의 Lv.2 바이러스 문제

엄청나게 큰 자료형을 다루는 문제

숫자가 큰 값을 사용할 때, 결과값을 어떤 수로 나누라고 하는 경우

모든 계산을 끝내고 나머지를 나누면 시간초과가 발생함

이 경우, 연산하는 과정에서 계속 나머지를 나누어 주면 된다

https://softeer.ai/practice/6284

1. 문제


간단 설명

바이러스가 숙주의 몸속에서 1초당 P배씩 증가한다.

처음에 바이러스 K마리가 있었다면 N초 후에는 총 몇 마리의 바이러스로 불어날까? N초 동안 죽는 바이러스는 없다고 가정한다.

1 ≤ K ≤ 108인 정수

1 ≤ P ≤ 108인 정수

1 ≤ N ≤ 106인 정수

가 주어질 때,

최종 바이러스 개수를 1000000007로 나눈 나머지를 출력하는 문제

2. 문제 분석


필요변수

바이러스 수 K, 증가율 P, 총 시간 N이 주어짐

바이러스의 수는 1초마다 P배 증가하므로

K = K * (P)^N 이 된다

K, P, N이 모두 최대값인 경우 2^6보다 크고, 2^7보다는 작다고 생각해보면

K = 2^6 * (2^6)^(2^6)이 된다

K = 약 2^390 정도 되기 때문에 int형으로는 처리 불가능. 혹은 계산하는 과정에서 이를 처리하는 과정이 필요함

int 자료형은 -2^31 ~ 2^31 (64bit 기준)까지 다룰 수 있기 때문에 오버플로우가 날 수 있으므로

long long int형을 사용함

long long int K

알고리즘

1
2
3
4
5
1. K, P, N을 입력받고
2. N번 2~3번 과정을 반복한다
3. (K * P) : 바이러스 K가 P배 증식한다
4. 3에서 계산한 (K * P)를 1000000007로 나머지 연산을 한다
5. K를 출력한다
  • 모두 계산하고 모듈러 연산을 수행하는 것과, (K * P)^N % MOD

    한번 계산을 할 때마다 모듈러 연산을 수행하는게 결과값이 같을까? (K * P % MOD)^N

  • 이를 적용하기 위해서는 모듈러 연산의 분배법칙에 대해 알아야함

    1
    2
    3
    
      (A + B) % p = ((A % p) + (B % p)) % p
      (A * B) % p = ((A % p) * (B % p)) % p
      (A - B) % p = ((A % p) - (B % p) + p) % p
    
  • 모듈러 연산은 곱셈에 대해 분배법칙이 성립하므로, 제곱도 문제없음

  • EX) k=2, p=2, n=5고, 10으로 모듈러 연산을 한다고 가정하면

    1) 전체 계산 후 모듈러 연산은 4, 8, 16, 32, 64이므로 결과는 4가 된다 2) 한번 계산할때마다 모듈러 연산을 수행하면 4, 8, 6(16%10), 2(12%10), 4 이므로 같음

3. 소스코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>

using namespace std;

int main(int argc, char** argv)
{
  int mod = 1000000007;
  int P, N;
  long long int K;

  cin >> K >> P >> N;
  
  // (K * P % MOD)^N
  while(N--){
    K = (K*P)%mod;
  }

  cout << K;
  
   return 0;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.