zoj 3591 Nim 博弈论

思路:先生成序列再求异或,最多的可能为n*(n+1)/2;

在去掉其中必败的序列,也就是a[i]=a[j]之间的序列。

代码如下:

 

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cmath>

 4 #include<algorithm>

 5 #include<cstring>

 6 #include<set>

 7 #include<vector>

 8 #define ll long long

 9 #define M 100005

10 #define inf 1e10

11 #define mod 1000000007

12 using namespace std;

13 int n,s,w,a[M];

14 int main()

15 {

16     int i,j,t;

17     scanf("%d",&t);

18     while(t--){

19         scanf("%d%d%d",&n,&s,&w);

20         int g=s;

21         a[0]=0;

22         for(i=1;i<=n;i++){

23             j=g;

24             if(j==0) j=g=w;

25             if(g%2==0) g=g/2;

26             else g=((g/2)^w);

27             a[i]=a[i-1]^j;

28         }

29         sort(a+1,a+n+1);

30         ll ans=(ll)(n+1)*n/2;

31         for(j=1,i=2;i<=n;i++){

32             if(a[i]==a[i-1]) j++;

33             else{

34                 if(a[i-1]==0) ans-=j;

35                 ans-=(ll)j*(j-1)/2;

36                 j=1;

37             }

38         }

39         ans-=(ll)j*(j-1)/2;

40         printf("%lld\n",ans);

41     }

42     return 0;

43 }
View Code

 

 

 

你可能感兴趣的:(ZOJ)