2016年省赛 G Triple Nim

2016年省赛 G Triple Nim
nim游戏,要求开始局面为先手必败,也就是异或和为0。
如果n为奇数,二进制下最后一位只有两种可能1,1,1和1,0,0,显然异或和为1,所以方案数为0
如果n为偶数,举个例子,14,二进制为1110,我们按位来拆
1110==1000+100+10
1000=100+100+000也就是上一位的1可以拆成下一位的两个1和一个0,对于n在二进制下的每一个1都可以拆成3种情况(0都有三个位置可以选),所以为3^x,又因为如果每次0都选在同一个位置,就会出现0的情况,所以-3。然后这3堆的顺序无关,再除6.

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<set>
 8 #include<map>
 9 #include<stack>
10 #include<cstring>
11 #define inf 2147483647
12 #define ls rt<<1
13 #define rs rt<<1|1
14 #define lson ls,nl,mid,l,r
15 #define rson rs,mid+1,nr,l,r
16 #define N 100010
17 #define For(i,a,b) for(long long i=a;i<=b;i++)
18 #define p(a) putchar(a)
19 #define g() getchar()
20 
21 using namespace std;
22 long long T;
23 long long n;
24 long long ans,t;
25 void in(long long &x){
26     long long y=1;
27     char c=g();x=0;
28     while(c<'0'||c>'9'){
29         if(c=='-')y=-1;
30         c=g();
31     }
32     while(c<='9'&&c>='0'){
33         x=(x<<1)+(x<<3)+c-'0';c=g();
34     }
35     x*=y;
36 }
37 void o(long long x){
38     if(x<0){
39         p('-');
40         x=-x;
41     }
42     if(x>9)o(x/10);
43     p(x%10+'0');
44 }
45 
46 long long ksm(long long a,long long b){
47     while(b%2==0){
48         a*=a;
49         b>>=1;
50     }
51     long long r=1;
52     while(b){
53         if(b%2==1)
54             r*=a;
55         a*=a;
56         b>>=1;
57     }
58     return r;
59 }
60 
61 void clear(){
62     t=0;
63 }
64 
65 int main(){
66     in(T);
67     while(T--){
68         clear();
69         in(n);
70         if(n%2==1)
71             o(0);
72         else{
73             while(n){
74                 if(n&1)
75                     t++;
76                 n>>=1;
77             }
78             o((ksm(3,t)-3)/6);
79         }
80         p('\n');
81     }
82     return 0;
83 }
View Code

 

posted @ 2019-04-30 11:23  WeiAR  阅读(167)  评论(0编辑  收藏  举报