版权声明:将来的你一定会感谢现在努力的你!!!! 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,且为整数。
输出描述:
一行一个整数代表小
第一步必胜策略的数量。
示例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;
}