1. 程式人生 > 實用技巧 >CF1451D Circle Game 題解

CF1451D Circle Game 題解

題意分析

給出一個半徑為 $d$ 的圓,以 $(0,0)$ 為起點,每次可以向上或向右移動 $k$ 個單位,先移出圓的為敗,求先手還是後手能贏。

思路分析

經過分析可以發現,無論對方怎麼走,先手可以保證在直線 $y=x+k$ 或 $y=x-k$ 上行走,後手可以保證在直線 $y=x$ 上行走。因此,當存在一個必勝點(即下一步必定出圓) $(x,y)$ 滿足 $|y-x|=k$ 且 $k|x$ ,則先手可以走到這裡保證必勝;同理,當存在一個必勝點 $(x,y)$ 滿足 $x=y$ 且 $k|x$ ,則後手可以走到這裡保證必勝。

具體實現

顯然我們應該首先在直線 $y=x$ 上走得儘量遠,然後判斷最遠的點是否為必勝點,如果是則後手勝,否則先手勝。具體判斷即看下一步是否會超出圓。顯然最遠即半徑長 $d$ ,而每走 $2$ 步走的距離即為 $\sqrt{2}k$ ,因此能走的最大步數為 $2\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor$ ,此時的座標為 $(k\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor,k\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor)$ 。下一步往上走和往右走都一樣,即走到 $(k\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor,k(\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor+1))$ ,用兩點間的距離公式判斷是否出圓即可,即最終只需要判斷 $(k\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor)^2+(k(\left \lfloor \frac{d}{\sqrt{2}k} \right \rfloor+1))^2>d^2$ ,若成立,則會超出,後手勝;否則先手勝。向下取整可以直接強制型別轉換為整型。

#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
#define ld long double
using namespace std;
int T;
ll d,k;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&d,&k);
        puts(pow(k*(ll)((ld)d/sqrt((ld)2)/k),2)+pow(k*(ll)((ld)d/sqrt((ld)2)/k+1),2)>d*d?"Utkarsh":"Ashish");
    }
    return 0;
}