【Wannafly挑战赛23】B 游戏【SG函数】

版权声明:将来的你一定会感谢现在努力的你!!!! https://blog.csdn.net/qq_37383726/article/details/82290188

链接:https://www.nowcoder.com/acm/contest/161/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小N和小O在玩游戏。他们面前放了n堆石子,第i堆石子一开始有ci颗石头。他们轮流从某堆石子中取石子,不能不取。最后无法操作的人就输了这个游戏。但他们觉得这样玩太无聊了,更新了一下规则。具体是这样的:对于一堆有恰好m颗石子的石头堆,假如一个人要从这堆石子中取石子,设他要取石子数为d,那么d必须是m的约数。最后还是无法操作者输。
现在小N先手。他想知道他第一步有多少种不同的必胜策略。一个策略指的是,从哪堆石子中,取走多少颗石子。只要取的那一堆不同,或取的数目不同,都算不同的策略。
输入描述:
第一行一个整数n。
接下来一行n个整数,分别代表每堆石子的石子数目。
数据保证输入的所有数字都不超过105,均大于等于1,且为整数。
输出描述:
一行一个整数代表小 N 第一步必胜策略的数量。
示例1
输入
10
47 18 9 36 10 1 13 19 29 1
输出
7
分析 : 暴力打出所有的石堆的SG值即可。
代码

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <list>
#include <string>
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, l, r) for(int i = l; i < r; i++)
#define per(i, r, l) for(int i = r; i >= l; i--)

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;

const int N = (int) 1e5 + 11;
const int M = (int) 400;
const int MOD = (int) 1e9 + 7;
const double EPS = (double) 1e-9;
const double PI = (double)acos(-1.0);
const int INF = (int) 0x3f3f3f3f;
const ll INFF = (ll) 0x3f3f3f3f3f3f3f3f;

ll add(ll x, ll y){return (x += y) >= MOD ? x - MOD : x;}
ll sub(ll x, ll y){return (x -= y) < 0 ? x + MOD : x;}
void read(int &x){
    char ch = getchar(); x = 0;
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
}
/*-----------------------------------------------------------------------------------*/

int SG[N], fac[400]; 
void  getSG(int n){ 
    memset(SG, 0, sizeof(SG)); 
    for(int i = 1; i  < n; i++){
        int id = 0;
        for(int j = 1; j * j <= i; j++){
            if(i % j == 0){
                fac[id++] = SG[i - j];
                fac[id++] = SG[i - i / j];
            }
        }
        sort(fac, fac + id);
        id = unique(fac, fac + id) - fac;
        int ans = 0;
        for(int i = 0; i < id; i++) if(ans != fac[i]) break; else ans++;    
        SG[i] = ans;
        //printf("# %d %d\n", i, ans);
    }
} 
int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
    getSG(100000 + 11);
    int n; scanf("%d", &n);
    vector<int>ve(n + 1);
    int ans = 0;
    for(int i = 0; i < n; i++) {
        scanf("%d", &ve[i]);
        ans ^= SG[ve[i]];
        //cout << SG[ve[i]] << " ";
    }
    int cnt = 0;
    for(int i = 0; i < n; i++){
        for(int j = 1; j * j <= ve[i]; j++){ // 对于每堆石子,把一步可以取的所有情况都遍历一遍
            if(ve[i] % j == 0){
                if(!((ans ^ SG[ve[i]]) ^ SG[ve[i] - j])) cnt++;
                if(ve[i] / j != j && !((ans ^ SG[ve[i]]) ^ SG[ve[i] - ve[i] / j]))  cnt++;
            }
        }
    }
    printf("%d\n", cnt);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37383726/article/details/82290188
今日推荐