[ARC91F]Strange Nim——SG函数 大佬们的博客 Some Links

题目大意:

n 堆石子,每堆石子有 a i 个,有一个数 k i 现在两个人博弈,每
个人每次至多可以拿走数量的为 x k i 石子, x 为当前这一堆石子的
数量,谁不能拿就输了,求谁赢。

思路:

这一看就是SG函数的题目,然后就不会做了。。。
我们固定了 k 的值为 3 后打表:
0 0 1 0 1 2 0 1 3 2
然后发现在 x % k == 0 时候,SG就等于 x / k ,这个时候SG函数的值是由前面 x / k 个数决定的,根据SG函数的定义,不难发现,前面的 x / k 个数就是 0 x k 1 ,但是顺序肯定是打乱的。
如何求 x % k ! = 0 时的函数值呢?发现当整除k相等的时候,都是由这个点往前 x k 个数的SG函数的值决定的,由于整除的时候的值我们是知道的,往后推一个就相当于 x x k 1 的值到了后面(这相当于是一个循环)。
然后我们就可以递归求函数了。但是会T。
每次往前递归是将坐标减去了 x k + 1 ,当k很大的时候会递归很多次,但是发现当k很大时候很长的一段区间减去的值都是相同的。所以我们直接一次性减去很多个相同的就可以了。
代码好短。。。

/*======================
 * Author : ylsoi
 * Problem : ARC91F
 * Algorithm : SG
 * Time : 2018.6.2
 * ====================*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstring>
#include<climits>
using namespace std;
void File(){
    freopen("ARC91F.in","r",stdin);
    freopen("ARC91F.out","w",stdout);
}
template<typename T>bool chkmax(T &_,T __){return _<__ ? (_=__,1) : 0;}
template<typename T>bool chkmin(T &_,T __){return _>__ ? (_=__,1) : 0;}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define inf INT_MAX
const int maxn=1000+10;
int n,a,k,ans;
int get_SG(int x){
    //cout<<x<<endl;
    if(x%k==0)return x/k;
    if((x-(x/k)-1)/k!=x/k)return get_SG(x-(x/k)-1);
    int b=x-x/k*k,t=b/((x/k)+1);
    return get_SG(x-t*((x/k)+1));
}
int main(){
    File();
    cin>>n;
    REP(i,1,n){
        cin>>a>>k;
        ans^=get_SG(a);
    }
    if(ans)puts("Takahashi");
    else puts("Aoki");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ylsoi/article/details/80546074
今日推荐