BOJ 24201 - Tankeläsning (Python3)

2024. 3. 10. 01:54Gold/Gold IV

오랜만에 문제 풀이 포스트를 올려 본다. 근래 검수다 뭐다 해서 바빴고, 검수하던 대회가 개최되자마자 신학기에 금요일과 토요일은 MatKor 온사이트 대회까지 있었다. 거의 모든 일정이 종료되고 나서야 이렇게 짬이 생긴 것 같다. 짬내서 쓰지 않으면 이제 시간도 잘 안 나는 듯 하고...

달려 있던 태그가 많은 조건 분기인데, 난 그런 거 귀찮아서 무작위화로 풀었다. 사실 조건 분기를 어떻게 해야 할지 감이 잡히기도 전에 무작위화 풀이가 생각이 난 게 크다.

 

그럼 본격적으로 풀이에 돌입해 보자. 의역이 좀 많다.


문제

Ett vanligt magitrick går till på följande vis:

다음과 같은 숫자 마술을 생각해 보자.

Tänk på ett tal. Subtrahera 1 från talet du tänkte på. Multiplicera resultatet med 3 och lägg till 9. Dela svaret med 3. Addera 5. Subtrahera talet du tänkte på från början. Talet du har kvar är 7.

어떤 숫자 하나를 떠올려 보라. 그리고 생각한 숫자에서 1을 빼라. 그 결과에 3을 곱한 뒤 9를 더하여라. 그 결과를 3으로 나누어라. 그리고 5를 더한 뒤, 맨 처음 떠올렸던 숫자를 빼라. 그렇다면 그 결과는 7이다.

Självklart är ingen verklig tankeläsning involverad. Om vi kallar det ursprungliga talet för \(x\) får vi genom att utföra operationerna uttrycken

물론 이는 독심술과는 연관이 없다. 맨 처음 떠올렸던 숫자를 \(x\)라고 부르면, 다음과 같은 순서로 연산을 수행하게 된다.

\[\begin{array}{rcl} (x) - 1 & = & x - 1 \\ (x - 1) * 3 & = & 3x - 3 \\ (3x - 3) + 9 & = & 3x + 6 \\ (3x + 6)\ /\ 3 & = & x + 2 \\ (x + 2) + 5 & = & x + 7 \\ (x + 7) - x & = & 7 \end{array}\] 

Alltså kommer vi alltid få talet 7 på slutet!

보다시피, \(x\)에 무관하게 항상 결과는 7이다!

Johan vill imponera på sina kompisar genom att utföra en liknande tankeläsning. Tyvärr är han inte så bra på matte, så han behöver hjälp att ta reda på om hans eget magitrick faktiskt fungerar.

요한은 이와 비슷한 마술을 통해서 친구들에게 깊은 인상을 남기고 싶어한다. 안타깝게도 요한은 수학을 그렇게 잘 하지 못하기 때문에, 자신의 마술이 실제로 효과가 있는지 알아내기 위해 도움을 필요로 한다.

 

입력

Den första raden innehåller ett heltal \(N\) \((1 \le N \le 10)\) - antalet operationer som magitricket består av.

첫 번째 줄에 마술의 연산 횟수를 나타내는 양의 정수 \(N\)이 주어진다. \((1\le N\le 10)\)

De nästa \(N\) raderna beskriver varje operation med hjälp av två mellanslagsseparerade tecken. Det första tecknet kommer att vara ett av '+', '-', '*' och '/', och beskriver operationen som utförs. Det andra tecknet anger talet operationen utförs med, och kommer att vara antingen en siffra 0-9, eller ett 'x'. I det senare fallet ska du utföra operationen med talet som man ursprungligen tänkte på i stället.

두 번째 줄부터 \(N\)개의 줄에 걸쳐 각 연산을 설명하는 두 문자가 공백으로 구분되어 주어진다. 첫 번째 문자는 '+', '-', '*', '/' 중 하나로 현재 수행 중인 연산의 종류를 나타낸다. 두 번째 문자는 연산을 수행하는 숫자를 나타내며, 이는 0부터 9까지의 숫자 혹은 'x'이다. 후자의 경우 맨 처음에 생각했던 숫자를 이용하여 연산을 수행하여야 한다.

Du kommer aldrig få kommandot "/ x" eller "/ 0".

"/ x"나 "/ 0"은 입력으로 들어오지 않는다.

 

예제 입력)

# 예제 입력 1
6
- 1
* 3
+ 9
/ 3
+ 5
- x

# 예제 입력 2
6
- 1
* 3
+ 9
/ 2
+ 5
- x

# 예제 입력 3
6
+ 2
- x
* x
/ 2
+ 3
- x

# 예제 입력 4
5
+ 7
* x
* 0
* x
- 7

# 예제 입력 5
1
* x

 

출력

Om magitricket fungerar, d.v.s. om man alltid får samma tal i slutet oavsett vad man började med, och det talet dessutom är ett heltal, ska du skriva ut talet. I annat fall ska du skriva ut "Nej".

마술이 정상적으로 작동하는 경우, 곧 무엇으로 시작하건 항상 마지막에 같은 숫자가 나오며 그 숫자가 정수일 때 해당하는 정수를 출력하라. 그렇지 않으면 "Nej"를 출력하라.

Observera att det enbart är sluttalet som måste vara ett heltal - tal som uppträder i uträkningen behöver inte vara det.

마술 중간에 숫자가 정수가 아니더라도 최종 결과만 정수라면 상관 없음에 유의하라.

 

예제 출력)

# 예제 출력 1
7

# 예제 출력 2
Nej

# 예제 출력 3
3

# 예제 출력 4
-7

# 예제 출력 5
Nej

 


내 코드

from random import randint
from collections import deque
from fractions import Fraction
a = Fraction(randint(1,1000))
b = Fraction(randint(1,1000))
c = Fraction(randint(1,1000))
f0,f1,f2,f3 = Fraction(-1),a,b,c
for _ in range(int(input())):
    op,val = input().split()
    if val == 'x':
        if op == '+':
            f0 += Fraction(-1); f1 += a; f2 += b; f3 += c
        elif op == '-':
            f0 -= Fraction(-1); f1 -= a; f2 -= b; f3 -= c
        elif op == '*':
            f0 *= Fraction(-1); f1 *= a; f2 *= b; f3 *= c
        elif op == '/':
            f0 /= Fraction(-1); f1 /= a; f2 /= b; f3 /= c
    else:
        val = Fraction(val)
        if op == '+':
            f0 += val; f1 += val; f2 += val; f3 += val
        elif op == '-':
            f0 -= val; f1 -= val; f2 -= val; f3 -= val
        elif op == '*':
            f0 *= val; f1 *= val; f2 *= val; f3 *= val
        elif op == '/':
            f0 /= val; f1 /= val; f2 /= val; f3 /= val
s = list({f0,f1,f2,f3})
if len(s) == 1: print(s[0] if s[0].denominator == 1 else 'Nej')
else: print('Nej')

 

0이나 x로 나누는 입력은 주어지지 않으므로, 정직하게 연산하더라도

계산을 전부 마치면 최종 결과는 x에 대한 함수가 될 것이다. 만약 마술이 성립하지 않는다면, 최종 결과가 상수함수가 아니라면. 높은 확률로 x가 달라지면 최종 결과 역시 달라질 것이다.

기적적으로 겹친다고 하더라도 수 4개의 결과가 전부 겹칠 확률은 0에 가까울 것이다. 그래서 -1 하나와, 1부터 1000까지의 수 중 임의로 뽑은 것들 세 개로 문제에서 정확히 하라는 대로만 수행해 주면 그 결과가 모두 같고 정수인지 아닌지에 따라서 맞춰 출력해주면 끝이다.

 

이로서 24201번의 풀이를 마친다.

 

 

 

728x90

'Gold > Gold IV' 카테고리의 다른 글

BOJ 16563 - 어려운 소인수분해 (Python3)  (0) 2022.11.28
BOJ 26008 - 해시 해킹 (Python3)  (0) 2022.11.20