ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1048 游戏 sg函数变式 博弈论

2022-07-30 22:00:12  阅读:119  来源: 互联网

标签:10 1048 变式 int res 石子 sg define


链接:https://ac.nowcoder.com/acm/contest/26656/1048
来源:牛客网

题目描述

小N和小O在玩游戏。他们面前放了n堆石子,第i堆石子一开始有ci颗石头。他们轮流从某堆石子中取石子,不能不取。最后无法操作的人就输了这个游戏。但他们觉得这样玩太无聊了,更新了一下规则。具体是这样的:对于一堆有恰好m颗石子的石头堆,假如一个人要从这堆石子中取石子,设他要取石子数为d,那么d必须是m的约数。最后还是无法操作者输。
现在小N先手。他想知道他第一步有多少种不同的必胜策略。一个策略指的是,从哪堆石子中,取走多少颗石子。只要取的那一堆不同,或取的数目不同,都算不同的策略。

输入描述:

第一行一个整数n。
接下来一行n个整数,分别代表每堆石子的石子数目。
数据保证输入的所有数字都不超过10
5
,均大于等于1,且为整数。

输出描述:

一行一个整数代表小$N$第一步必胜策略的数量。
示例1

输入

复制
10
47 18 9 36 10 1 13 19 29 1

输出

复制
7

 

分析

标准的集合类nim游戏问题。

普通的集合类nim游戏:有几种取法,在n堆石子里取,问最终结果。将每一堆石子的sg值算出来就是答案。

这题:每堆石子可以取自己的因子的数量的石子,从n堆取,问最终结果。要将每一堆石子的sg值算出来就很复杂,需要用到之前的状态,而且还要求出有多少种不同取法。

问题1:算出每堆石子的sg值

 

由于石子数目小于一万,所以可以从小到大dp,预处理出所有石子的sg值,当求后面的石子的sg值的时候,前面所有石子的sg值已经求过了

设f[i] 表示 i 个石子的sg值

状态转移:设i 的因子d,f[i] = mex(f[i-d1],f[i-d2],f[i-d3]....)

 

问题2:通过算出的sg值,判断第一步有多少取法

 

假设已经求出了所有sg值的异或和 sum

要获得胜利,就要让对方变成必败状态,即sg值为0的状态。

让sum 异或 每堆石子数目。消去当前堆石子的总数的影响。

遍历当前堆石子的所有因子,如果异或这个因子能够使sum 值为0,即为必败状态。方案数 + 1

 

#include<bits/stdc++.h>
#define TLE ios::sync_with_stdio(0),cin.tie(0)
#define endl "\n"
#define FILE "a"
#define pb push_back
#define gg exit(0);
#define rt return;
#define bd cout<<"debug"<<endl;
#define db(x) cout<<#x<<':'<<x<<endl;
#define dbb(i,a) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<endl;
#define dbbb(i,a,b) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<#b<<':'<<b<<endl;
#define YES cout<<"YES"<<endl;
#define TIME cout<<"RuningTime: "<<clock()<<"ms\n";
#define Yes cout<<"Yes"<<endl;
#define NO cout<<"NO"<<endl;
#define No cout<<"No"<<endl;
#define None cout<<-1<<endl;
#define el cout<<endl;
#define x first
#define y second
#define V vector
#define fo(i,j,n) for(int i = j;i<=n;i++)
#define of(i,n,j) for(int i = n;i>=j;i--)
#define all(a) a.begin(),a.end()
#define alll(a) a.begin()+1,a.end()
#define ms(a,b) memset(a, b, sizeof(a))
#define lowbit(x) (x&-x)
#define gcd(a,b) __gcd(a,b)
#define DEBUG 11243
using namespace std;
void clapping() {
    #if DEBUG == 1
    srand(time(NULL)+rand());
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    #endif
}
template<class T>inline void read(T &res) {
    char c;T flag = 1;
    while((c = getchar()) < '0' || c > '9') if(c == '-') flag = -1;res = c - '0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
typedef pair<int,int> pii;
typedef pair<long,long>pll;
typedef long long ll;
const int inf = 1e9;
const ll INF = 1ll<<60;
const double eps = 1e-8;
int dy[] = {1,0,-1,0,1,1,-1,-1};
int dx[] = {0,1,0,-1,1,-1,1,-1};
template<class T> T qmi(T a,T b,T p) {
    T res = 1;
    for(;b;b>>=1,a=1ll*a*a%p)
        if(b&1)res = 1ll*res*a%p;
    return res;
}
template<class T> T exgcd(T a,T b,T &x,T &y) {
    if(b == 0) {x = 1;y = 0;return a;}
    ll d = gcd_ed(b,a%b,y,x);
    y = y - a / b * x;
    return d;
}
/*文档区


*/

//-------------------------代码----------------------------

//#define int ll
const int mod = 1e9 +7,md = 1e9+6,N = 1e5+10;
int a[N];
int sg[N];
vector<int>G[N];
int vis[N];

void solve()
{
    int cnt = 0;
    for(int i = 1;i<N;i++) {
        cnt ++ ;
        int k = sqrt(i);
        for(int j = 1;j<=k;j++) {
            if(i % j == 0) {
                vis[sg[i-j]]=cnt;
                if(j*j!=i) vis[sg[i-i/j]]=cnt;
            }
        }
        for(int j = 0;j<=N-10;j++)
            if(vis[j] != cnt) 
            {
                sg[i] = j;
                break;
            }
    }
    int n;cin>>n;
    int sum = 0;
    for(int i = 1;i<=n;i++) {
        cin>>a[i],sum ^= sg[a[i]];
    }
    int ans = 0;
    for(int i = 1;i<=n;i++) {
        sum ^= sg[a[i]];
        int k = sqrt(a[i]);
        for(int j = 1;j<=k;j++) {
            if(a[i] % j == 0) {
                if((sg[a[i] - j]^sum) == 0) {ans ++ ;}
                if(j * j != a[i] && ( sg[a[i] - a[i] / j] ^ sum) == 0) ans ++ ;
            }
        }
        sum ^= sg[a[i]];
    }
    cout<<ans<<endl;
}

signed main(){
    clapping();TLE;

//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:10,1048,变式,int,res,石子,sg,define
来源: https://www.cnblogs.com/er007/p/16535928.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有