Codeforces Round #685 (Div. 2) D

Codeforces Round #685 (Div. 2) D

大意

略...

思路

按照样例的图示,我们不妨考虑可行走的格点范围。

它的边缘一定如下图。

img

如果走到了边缘的两个格点上,那么下一步一定无法走了,也就是说能够先走到边缘格点的人一定胜利。

我们不妨考虑一下后手必胜的情况下。

此时若先手往右,那么后手往上,或相反。

容易得到一组不等式, 其中 (a) 是回合数。

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

即我们找到最大的 (a) ,让第一个式子满足,如果第二个式子也满足,那么后手必胜。

那么如果第二个式子不满足呢?

不失一般性,不妨假设先手向上走了一次,然后先手后手交换。

此时原来的后手就处于原来先手的的情况下。

因为

(egin{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;
}
原文地址:https://www.cnblogs.com/ullio/p/14021156.html