ATCoder arc091_d 题解

题目大意

有n堆石子,每堆石子两个参数(A, K),每次取出[1, A/K]个石子,两个人轮流操作,不能取者输。求先手还是后手必胜。

解法

考虑SG函数sg(i)

sg(i) = i%k==0 ? i/k : sg(i-(i/k)-1)

考虑证明,可以用数学归纳法,对于每个位置,他前面(i-1)/k+1个位置包括了[0, (i-1)/k]。那么该位置要么为sg(i-(i/k)-1),要么为i/k。

代码

#include <cstdio>

using namespace std;

int f(int a, int k) {
    if (a%k==0) return a/k;
    else if (a%k>=a/k+1) return f(a-(a%k)/(a/k+1)*(a/k+1), k);
    else return f(a-a/k-1, k);
}

int main() {
#ifdef DEBUG
    freopen("src.in", "r", stdin);
    freopen("src.out", "w", stdout);
#endif

    int n, ans=0;
    scanf("%d", &n);
    for (int i=1; i<=n; i++) {
        int a, k;
        scanf("%d %d", &a, &k);
        ans ^= f(a, k);
    }
    printf(ans ? "Takahashi\n" : "Aoki\n");

    fclose(stdin);
    fclose(stdout);
    return 0;
}

posted @ 2020-10-15 21:21  鼠曲雪兔子  阅读(95)  评论(0编辑  收藏  举报