转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents
by---cxlove
题目:按照某种规律生成一个序列,选中某段连续的序列玩NIM游戏,先手能必胜的有多少种。
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4675
乍一看毫无头绪啊。序列貌似会形成循环,可是数量如此之大。
先按照规则生成序列。保存前i个堆的异或值,存在nim[i]。
如果想要必胜,是选中连续的数异或不为0,如果存在nim[i]==nim[j]则表示i+1,i+2……j的异或值0,则是一组必败的局面。
这样我们便想到从对立而考虑,总共的选择是n*(n+1)/2。
将nim排序,找出相同 的nim值有多少个,便可以统计出有多少必败的局面。
同时注意nim[i]为0的话,现在从1----i便是必败局面,也要减掉。
另外注意int溢出
#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;
int a[100005],nim[100005];
int main(){
int t,n,s,w;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&s,&w);
int g=s,ret=0;
for(int i=0;i<n;i++){
a[i]=g;
if(a[i]==0) a[i]=g=w;
if(g%2==0) g/=2;
else g=(g/2)^w;
ret^=a[i];
nim[i]=ret;
}
sort(nim,nim+n);
LL sum=(LL)n*(n+1)/2;
int len=1;
for(int i=1;i<n;i++){
if(nim[i]==nim[i-1])
len++;
else{
if(nim[i-1]==0)
sum-=len;
sum-=(LL)len*(len-1)/2;
len=1;
}
}
sum-=(LL)len*(len-1)/2;
printf("%lld\n",sum);
}
return 0;
}
分享到:
相关推荐
zoj 3590 -3+1.md
深度搜索 回溯 int main { string s1 s2; while cin >> s1 >> s2 { count 0; cout << "[" << endl; if s1 length s2 length BackTrake s1 s2 ;... [更多]
ZOJ解题报告ZOJ解题报告ZOJ解题报告ZOJ解题报告
zoj题目简单归类zoj题目简单归类zoj题目简单归类
zoj_1004.cpp 求单词字母进出栈后能形成目标串的进出方案 广度优先搜索求解
acm中zoj1002的可运行C++程序
包含了zoj700多道题目的源代码,在做题时可以参考
Problem Arrangement zoj 3777
ZOJ题目答案源码
一个非常非常非常非常实用的zoj结题代码
学习ACM程序设计的朋友一定要看,这是训练必备的POJ ZOJ题目分类及解题思路
ZOJ1805代码
zoj 1003 c语言的,要写这么多描述吗。。
本代码是zoj上AC的1951的代码,把双重循环简化为O(n),不过素数判断的改进还不够
zoj1027解题指南和代码,还不错,是学校培训给的。
浙大ZOJ题目分类,可以让你更方便快速锁定那你想要联系的题目,是自己快速提高·
ZOJ题解集合-截至2835。共1244个文件,C/C++,有重复
zoj 题库 详细解答 解题代码 acm
zoj4041正确题解源代码,以及运行程序
大学ACM竞赛,ZOJ 1733 运用递归(优化)的方法。ac的代码。