`
java-mans
  • 浏览: 11339943 次
文章分类
社区版块
存档分类
最新评论

ZOJ 3529 A Game Between Alice and Bob (数论+SG博弈)

 
阅读更多

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove

题意:有N堆石头,每次选中某一堆,把数量替换成原先的因子。全部为1则结束。

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4464

乍一看,SG博弈,一个状态的后继就是所有因子,然后MEX操作,果断TLE。不过思想还算正确。

以下为TLE代码

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define C    240
#define TIME 10
#define inf 1<<25
#define LL long long
using namespace std;
int sg[5000005];
int get_sg(int n){
    if(sg[n]!=-1)
        return sg[n];
    int vis[1005];
    memset(vis,0,sizeof(vis));
    vis[0]=1;
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            vis[get_sg(i)]=1;
            vis[get_sg(n/i)]=1;
        }
    }
    for(int i=0;;i++)
        if(vis[i]==0)
            return sg[n]=i;
}
int main(){
    int n,cas=0,a[100005];
    memset(sg,-1,sizeof(sg));
    sg[1]=0;
    for(int i=5000000;i;i--){
        if(sg[i]==-1)
           get_sg(i);
    }
    while(scanf("%d",&n)!=EOF){
        int ret=0;
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            ret^=sg[a[i]];
        }
        printf("Test #%d: ",++cas);
        if(ret==0) puts("Bob");
        else{
            printf("Alice ");
            for(int i=0;i<n;i++){
                if(a[i]>(ret^sg[a[i]])){
                    printf("%d\n",i+1);
                    break;
                }
            }
        }
    }
    return 0;
}


仔细分析,对于某一个数,他的后继有多少个呢,其实就是质因子的个数。

比如说12,他的后继有6,4,2这3个。正好是他的质因子个数,2,2,3。相当于NIM游戏中,3个石头,每次可以拿走1-3个。

那我们打出素数表,然后暴力求出质因子个数就行了,也可以DP预处理质因子个数。

转换成NIM之后,考虑必胜的第一步策略。同样还是NIM一样。转换成拿走几个因子。

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define C    240
#define TIME 10
#define inf 1<<25
#define LL long long
using namespace std;
bool flag[5000005]={0};
int cnt=0,prime[5000000];
int sg[5000005];
void Prime(){
  //  prime[cnt++]=1;
    for(int i=2;i<=sqrt(1.0+5000000);i++){
        if(flag[i]) continue;
        prime[cnt++]=i;
        sg[i]=1;
        for(int j=2;j*i<=sqrt(1.0+5000000);j++)
            flag[i*j]=true;
    }
}
int get_sg(int n){
    if(sg[n]!=-1) return sg[n];
    int k=0,t=n;
    for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
        if(n%prime[i]==0){
            while(n%prime[i]==0){
                k++;
                n/=prime[i];
            }
        }
    if(n>1)
        k++;
    return sg[t]=k;
}
int main(){
    memset(sg,-1,sizeof(sg));
    sg[1]=0;
    Prime();
    int n,cas=0,a[100000];
    while(scanf("%d",&n)!=EOF){
        int ret=0;
        for(int i=0;i<n;i++){
           scanf("%d",&a[i]);
           ret^=get_sg(a[i]);
        }
        printf("Test #%d: ",++cas);
        if(ret==0)  puts("Bob");
        else{
            printf("Alice ");
            for(int i=0;i<n;i++)
                if(sg[a[i]]>(ret^sg[a[i]])){
                    printf("%d\n",i+1);
                    break;
                }
        }
    }
    return 0;
}




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics