LoginSignup
3
0

More than 3 years have passed since last update.

【Python】ABC191 D - Circle Lattice Points (誤差問題)【AtCoder】

Last updated at Posted at 2021-02-07

ABC191 D - Circle Lattice Points

ふりかえりをしていたが、
解説見て、解き方わかったのにどうしてもWAが消えない
10000倍して、整数でやってるつもりなのに、どうして!!!
ということでACの人たちのコードみたら、
10000倍してる人もルート計算で結局Decimal使ってるっぽい!

結論

Decimal最強伝説!
誤差問題はDecimalで提出しましょう。
※ちなみに、PyPyはDecimal計算遅いので、Pythonで提出しましょう。

以下結論までの軌跡・・・

提出したコードたちはこちら

WA1.py
import math,sys
def LS(): return list(sys.stdin.readline().rstrip().split())
#############################
from decimal import Decimal
n = 10000
X,Y,R = [int(Decimal(x)*n) for x in LS()]

ans = 0
for y in range(math.ceil((Y-R)/n),math.floor((Y+R)/n)+1):
    z = (R**2-(Y-y*n)**2)**0.5
    ans += math.floor((X+z)/n)-math.ceil((X-z)/n)+1

print(ans)

スクリーンショット 2021-02-07 14.09.09.png

ansの足し算のところで、整数+小数だから、そこで誤差発生してるのかな?
zを整数にしてみよう。

WA2.py
import math,sys
def LS(): return list(sys.stdin.readline().rstrip().split())
#############################
from decimal import Decimal
n = 10000
X,Y,R = [int(Decimal(x)*n) for x in LS()]

ans = 0
for y in range(math.ceil((Y-R)/n),math.floor((Y+R)/n)+1):
    z = int((R**2-(Y-y*n)**2)**0.5)
    ans += math.floor((X+z)/n)-math.ceil((X-z)/n)+1

print(ans)

スクリーンショット 2021-02-07 14.09.09.png

なんでや・・・

原因は「**0.5」

ルートを出すときに、0.5っていうfloat型使ってるんじゃい!!!
誤差がでるんじゃい!!!
無意識だった。。。

AC1.py
import math,sys
def LS(): return list(sys.stdin.readline().rstrip().split())
#############################
from decimal import Decimal
n = 10000
X,Y,R = [int(Decimal(x)*n) for x in LS()]

ans = 0
for y in range(math.ceil((Y-R)/n),math.floor((Y+R)/n)+1):
    z = int(Decimal(R**2-(Y-y*n)**2).sqrt())
    ans += math.floor((X+z)/n)-math.ceil((X-z)/n)+1

print(ans)

スクリーンショット 2021-02-07 14.24.01.png

というかそもそも誤差問題全部Decimalで計算すれば最強じゃね?
10000とかかける必要なくね???

AC2.py
import math,sys
def LS(): return list(sys.stdin.readline().rstrip().split())
#############################
from decimal import Decimal
X,Y,R = [Decimal(x) for x in LS()]

ans = 0
for y in range(math.ceil(Y-R),math.floor(Y+R)+1):
    z = (R**2-(Y-y)**2).sqrt()
    ans += math.floor(X+z)-math.ceil(X-z)+1

print(ans)

スクリーンショット 2021-02-07 14.24.01.png

まとめ

Decimal最強伝説!
誤差問題はDecimalで提出しましょう!!!

おわり!!!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0