zoukankan      html  css  js  c++  java
  • 【题解】Acwing 235. 魔法珠

    Acwing 235. 魔法珠

    ( ext{Solution:})

    其实思考下发现不好做之后就知道必须要 SG 函数了……拿简单题复习一下 SG 函数吧 顺便也碰到了一些细节

    首先我们发现,每一个数字都会被拆分成若干其他数字,并且会被拿走。而且也容易证明这是一个公平组合游戏。那么 SG 函数在这一题就成立了。我们来分析如何应用:

    首先,每个数字都是一个小游戏,所以它们必然有自己的 SG 函数值。所以第一个任务应该是求出每个数字的 SG 函数。

    其次,整体局面就是一个若干 SG 函数的拼接,所以我们求出 SG 函数之后利用 SG 函数引理异或起来即可。

    那么如何求一个数的 SG 函数?这里有细节要注意。

    首先,通过定义我们容易知道,一个数的 SG 函数值应当是其所有后继状态的 SG 函数的 mex 运算结果。而这句话乍看很简单,但也是有细节要注意的:

    我们求的是其所有后缀状态的 SG ,而非后缀产生的游戏的 SG !

    这一题中体现尤为明显。因为在暴力搜索求 SG 的时候,我们将其质因数分解之后,很容易直接求其所有质因数 SG 的 mex 。这显然是错的,因为这些质因数对应的游戏并不是这个游戏操作后的状态。

    对应的状态应当是,由当前执子者拿掉一堆石子后的状态。所以我们要求的 SG 应当是选出 (n-1) 个数的 SG 的异或值。

    分析到这里细节就差不多了。直接暴搜即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1001;
    int sg[N],a[N],n;
    int SG(int x){
    	if(~sg[x])return sg[x];
    	vector<int>vec;
    	vec.emplace_back(1);
    	int v=x;
    	for(int i=2;i*i<=x;++i){
    		if(v%i==0){
    			vec.emplace_back(i);
    			if(i*i!=x)vec.emplace_back(x/i);
    		}
    	}
    	sort(vec.begin(),vec.end());
    	unordered_map<int,int>vis;
    	int sum=0;
    	for(int i=0;i<(int)vec.size();++i)sum^=SG(vec[i]);
    	for(int i=0;i<(int)vec.size();++i)vis[sum^SG(vec[i])]=1;
    	sg[x]=0;
    	while(vis[sg[x]])++sg[x];
    	return sg[x];
    }
    int main(){
    	freopen("in.txt","r",stdin);
    	for(int i=0;i<=1000;++i)sg[i]=-1;
    	sg[1]=0;sg[0]=0;
    	while(~scanf("%d",&n)){
    		for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    		int ans=0;
    		for(int i=1;i<=n;++i)ans^=SG(a[i]);
    		if(ans==0)puts("rainbow");
    		else puts("freda");
    	}
    	return 0;
    }
    
  • 相关阅读:
    iis6 , URL重写HTM文件名后,出现真实的HTM文件不能访问的解决
    pe如何安装ios系统
    ASP.NET Word转为PDF
    asp.net 操作word 权限
    windows server 2008 r2 修改远程登入的端口号(3389)
    A
    A Bug
    亲戚
    Kruskal
    HDOJ ——统计难题
  • 原文地址:https://www.cnblogs.com/h-lka/p/15379558.html
Copyright © 2011-2022 走看看