K 倍动态减法

一堆石子有 n 个,第一次可以取 1 ~ n - 1 个石子,之后至多可取 k 倍上次所取的石子数。

k 时的先手必败集合是一个 k 次的递推。

k = 1: an = 2 a{n - 1}

k = 2: an = a{n - 1} + a_{n - 2}

k = 3: an = a{n - 1} + a{n - 2} - a{n - 3} + 1

#include <cstdio>

const int MAXN = 2000005;

int a[MAXN], b[MAXN];

int main() {
    int n, k; // n <= 100,000,000, k <= 100,000
    scanf("%d %d", &n, &k);

    a[0] = b[0] = 1;
    int i = 0, j = 0;
    while (a[i] < n) {
        ++i;
        a[i] = b[i - 1] + 1;
        while (a[j + 1] * k < a[i]) ++j;
        if (a[j] * k < a[i]) b[i] = a[i] + b[j];
        else b[i] = a[i];
    }

    if (a[i] == n) puts("Lose");
    else {
        int ans = 0;
        while (n) {
            if(n >= a[i]) {
                n -= a[i];
                ans = a[i];
            }
            --i;
        }
        printf("%d\n",ans);
    }

    return 0;
}

results matching ""

    No results matching ""