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(' '); 81 } 82 return 0; 83 }