• AtCoder Regular Contest 091F


    AtCoder Regular Contest 091F - Strange Nim

    题目大意

    • N N N堆石子,每堆有 A i A_i Ai颗,两个人轮流取,每次选择其中一堆,当其剩下石子数为 x x x时,取的石子数不能超过 x / k x/k x/k下取整,每堆的 k k k是一个定值,不能取的人为负。
    • N ≤ 200 N≤200 N200
    • A i , k i ≤ 1 0 9 A_i,k_i≤10^9 Ai,ki109

    题解

    • 显然可以先计算出对于不同 k k k的每个状态的SG函数值,从 0 0 0开始打个表出来,
    • 把这些数 k k k个一行,会发现第一列从 0 0 0开始依次递增 1 1 1,第一行全为 0 0 0,当把第一列的数全部删去后,剩下的数也满足这个规律,
    • 那么一开始先把 A i A_i Ai加一,再这样一直删下去就可以求出当前 A i A_i Ai的函数值。
    • 一开始以为这样就可以过了,其实发现是会TLE的,
    • 有可能 A i A_i Ai特别大,但 A i / k i A_i/k_i Ai/ki也特别大,以至于每次只能删去很少的几个数,需要重复操作很多遍,
    • 那么直接考虑一次性多删一些。
    • 每次相当于给 A i A_i Ai减去 ( A i − 1 ) / k (A_i-1)/k (Ai1)/k下取整,当 ( A i − 1 ) / k (A_i-1)/k (Ai1)/k下取整的值没变时,每次减去的数值就是一样的,那么直接就算最多可以先重复删多少个这个值即可。

    代码

    #include<cstdio>
    using namespace std;
    int solve(int x, int k) {
    	if(x <= k) return 0;
    	if((x - 1) % k == 0) return (x - 1) / k;
    	int d = (x - 1) / k * k + 1, t = (x - 1) / k + 1;
    	return solve(x - ((x - 1 - d) / t + 1) * t, k);
    }
    int main() {
    	int n, s = 0, x, k;
    	scanf("%d", &n);
    	while(n--) {
    		scanf("%d%d", &x, &k);
    		s ^= solve(x + 1, k);
    	}
    	if(s) printf("Takahashi"); else printf("Aoki");
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    AngularJs $location 和 $window
    AngularJS——自定义服务详解(factory、service、provider)
    angularAMD+requireJs
    angular ui-router时要使用html5Mode=true
    CSS3的calc()使用
    React Ajax this.IsMounted() is not a function
    css有用的代码片段
    8908
    454
    234
  • 原文地址:https://www.cnblogs.com/LZA119/p/13910017.html
Copyright © 2020-2023  润新知