sg函数训练——开窍篇

这篇博客探讨了sg函数在博弈策略中的应用,通过分析经典题目如hdu 3032 Nim or not Nim?和acdream 1112 Alice and Bob,深入理解sg函数的计算和其在解决数论问题中的作用。同时,提到了Treblecross问题,展示了sg函数在棋盘游戏中如何决定胜负策略。
摘要由CSDN通过智能技术生成

个人觉得,能做一道经典的题并理解透彻,往往比做对难度系数很大的题目更有意义。最近又训练了博弈,记录一些题目,来个小总结。

hdu 3032 Nim or not Nim?

http://acm.hdu.edu.cn/showproblem.php?pid=3032
大意:和普通的nim游戏相比,这里新添加了一种操作,可以把数字分成更小的两份。
分析:
sg[0]=0
当i=1,取走1后剩下0,mex[1]=1. sg[1]=1
当i=2时,可以取1,2,剩下1,0,sg[1]=1,sg[0]=0,分解成1+1,sg[1]^sg[1]=0,即分解相同的两部分和取走全部的效果是一样的。mex(2)=2 sg[2]=2
当i=3时,可以取1,2,3,剩下2,1,0,sg[2]=2, sg[1]=1, sg[0]=0,分解: sg[1]^sg[2]=3,所以mex(3)=4. sg[3]=4
当i=4时,取:1,2,3,4,剩下:sg[3]=4, sg[2]=2, sg[1]=1, sg[0]=0, 分解: sg[1]^sg[3]=5 mex(5)=3. sg[4]=3.

打表:

int sg[N];
bool vis[N];
void init(int n){
    int i,j;
    for(i=2;i<n;i++){
        memset(vis,0,sizeof(vis));
        for(j=1;j<=n;j++) vis[sg[i-j]]=1; // 取
        for(j=1;j+j<=n;j++) vis[sg[j]^sg[i-j]]=1;  // 分解
        j=0;
        while(vis[j]) j++;
        sg[i]=j;
    }
}
/*
1: 1
2: 2
3: 4
4: 3
5: 5
6: 6
7: 8
8: 7
9: 9
10: 10
11: 12
12: 11
13: 13
14: 14
15: 16
16: 15
17: 17
18: 18
19: 20
20: 19
21: 21
22: 22
23: 24
24: 23
*/

得到规律:
sg[4n+3]=4n+4
sg[4n]=4n-1
sg[i]=i

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int main()
{
    //freopen("cin.txt","r",stdin);
    int n,t;
    cin>>t;
    while(t--){
        scanf("%d",&n);
        int a,ans=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a);
            if((a&3)==3) {  // a%4==3
                ans=ans^(a+1);
            }
            else if((a&3)==0){  // a%4==0
                ans=ans^(a-1);
            }
            else ans=ans^a;
        }
        if(ans) puts("Alice");
        else puts("Bob");
    }
    return 0;
}

acdream 1112 Alice and Bob

http://acdream.info/problem?pid=1112
大意:给出一堆数字,每一个数字可以被不是它本身的约数(包括1)替代,或者分解成两个约数。比如6可以变成:2, 3, (2,3)
分析:一开始使用直接分解计算的方法果断超时。事实上这个问题完全可以从另一个角度看&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值