1. 程式人生 > 實用技巧 >Codeforces Round #685 (Div. 2) D

Codeforces Round #685 (Div. 2) D

Codeforces Round #685 (Div. 2) D

大意

略...

思路

按照樣例的圖示,我們不妨考慮可行走的格點範圍。

它的邊緣一定如下圖。

如果走到了邊緣的兩個格點上,那麼下一步一定無法走了,也就是說能夠先走到邊緣格點的人一定勝利。

我們不妨考慮一下後手必勝的情況下。

此時若先手往右,那麼後手往上,或相反。

容易得到一組不等式, 其中 \(a\) 是回合數。

\(\begin{cases} (ak)^2+(ak)^2 \leq d^2 \\ ((a+1)k)^2+(ak)^2 > d^2 \end{cases}\)

即我們找到最大的 \(a\) ,讓第一個式子滿足,如果第二個式子也滿足,那麼後手必勝。

那麼如果第二個式子不滿足呢?

不失一般性,不妨假設先手向上走了一次,然後先手後手交換。

此時原來的後手就處於原來先手的的情況下。

因為

\(\begin{cases} ((a+1)k)^2+((a+1)k)^2 > d^2 \\ ((a+2)k)^2+(ak)^2 > ((a+1)k)^2+((a+1)k)^2 \end{cases}\)

所以此時的後手只需要重複原來後手的方案,一定必勝。

程式碼

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)

const int mod = 998244353;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;

ll t, d, k;

int main() {
    cin >> t;
    while(t--) {
        cin >> d >> k;
        ll a = (ll)(sqrt(((d*d)/(k*k)/2)*1.0));
        while((pow(a+1,2)+pow(a,2))*(k*k) <= d*d) ++a;
        if(2*a*a*k*k > d*d) cout << "Ashish" << endl;
        else cout << "Utkarsh" << endl;
    }
    return 0;
}