题目意思很简单。
就是洗牌,抽出奇数和偶数,要么奇数放前面,要么偶数放前面。
总共2^N张牌。
需要问的是,给了A X B Y 问经过若干洗牌后,第A个位置是X,第B个位置是Y 是不是可能的。
Jason is not only an ACMer, but also a poker nerd. He is able to do a perfect shuffle. In a perfect shuffle, the deck containing K cards, where K is an even number, is split into equal halves of K/2 cards which are then pushed together in a certain way so as to make them perfectly interweave. Suppose the order of the cards is (1, 2, 3, 4, …, K-3, K-2, K-1, K). After a perfect shuffle, the order of the cards will be (1, 3, …, K-3, K-1, 2, 4, …, K-2, K) or (2, 4, …, K-2, K, 1, 3, …, K-3, K-1).
Suppose K=2^N and the order of the cards is (1, 2, 3, …, K-2, K-1, K) in the beginning, is it possible that the A-th card is X and the B-th card is Y after several perfect shuffles?
Suppose K=2^N and the order of the cards is (1, 2, 3, …, K-2, K-1, K) in the beginning, is it possible that the A-th card is X and the B-th card is Y after several perfect shuffles?
题目给的牌编号是1开始的,先转换成0开始。
一开始位置是0~2^N-1. 对应的牌是0~2^N-1
首先来看每次洗牌的过程。
对于第一种洗牌:将奇数放前面,偶数放后面。其实每个位置数的变化就是相当于循环右移一位,然后高位异或1.
对于第二种洗牌:讲偶数放前面,奇数放后面。其实每个位置数的变化就是相当于循环右移一位,然后高位异或0.
所以经过若干次洗牌,可以看成是循环右移了K位,然后异或上一个数。
所以对于题目的查询:
首先将A X B Y都减一。 然后枚举X,Y循环右移了K位以后,能不能同时异或上相同的数得到A,B
需要大数,然后转化成二进制就可以解决了。
循环右移X,Y,然后判断A ^ X 是不是等于 B ^ Y
7 #pragma comment(linker, "/STACK:1024000000,1024000000") 8 #include <stdio.h> 9 #include <string.h> 10 #include <iostream> 11 #include <algorithm> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 #include <string> 17 #include <math.h> 18 #include <stdlib.h> 19 #include <time.h> 20 using namespace std; 21 22 /* 23 * 完全大数模板 24 * 输出cin>>a 25 * 输出a.print(); 26 * 注意这个输入不能自动去掉前导0的,可以先读入到char数组,去掉前导0,再用构造函数。 27 */ 28 #define MAXN 9999 29 #define MAXSIZE 1010 30 #define DLEN 4 31 32 class BigNum 33 { 34 public: 35 int a[500]; //可以控制大数的位数 36 int len; 37 public: 38 BigNum(){len=1;memset(a,0,sizeof(a));} //构造函数 39 BigNum(const int); //将一个int类型的变量转化成大数 40 BigNum(const char*); //将一个字符串类型的变量转化为大数 41 BigNum(const BigNum &); //拷贝构造函数 42 BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算 43 friend istream& operator>>(istream&,BigNum&); //重载输入运算符 44 friend ostream& operator<<(ostream&,BigNum&); //重载输出运算符 45 46 BigNum operator+(const BigNum &)const; //重载加法运算符,两个大数之间的相加运算 47 BigNum operator-(const BigNum &)const; //重载减法运算符,两个大数之间的相减运算 48 BigNum operator*(const BigNum &)const; //重载乘法运算符,两个大数之间的相乘运算 49 BigNum operator/(const int &)const; //重载除法运算符,大数对一个整数进行相除运算 50 51 BigNum operator^(const int &)const; //大数的n次方运算 52 int operator%(const int &)const; //大数对一个int类型的变量进行取模运算 53 bool operator>(const BigNum &T)const; //大数和另一个大数的大小比较 54 bool operator>(const int &t)const; //大数和一个int类型的变量的大小比较 55 56 void print(); //输出大数 57 }; 58 BigNum::BigNum(const int b) //将一个int类型的变量转化为大数 59 { 60 int c,d=b; 61 len=0; 62 memset(a,0,sizeof(a)); 63 while(d>MAXN) 64 { 65 c=d-(d/(MAXN+1))*(MAXN+1); 66 d=d/(MAXN+1); 67 a[len++]=c; 68 } 69 a[len++]=d; 70 } 71 BigNum::BigNum(const char *s) //将一个字符串类型的变量转化为大数 72 { 73 int t,k,index,L,i; 74 memset(a,0,sizeof(a)); 75 L=strlen(s); 76 len=L/DLEN; 77 if(L%DLEN)len++; 78 index=0; 79 for(i=L-1;i>=0;i-=DLEN) 80 { 81 t=0; 82 k=i-DLEN+1; 83 if(k<0)k=0; 84 for(int j=k;j<=i;j++) 85 t=t*10+s[j]-'0'; 86 a[index++]=t; 87 } 88 } 89 BigNum::BigNum(const BigNum &T):len(T.len) //拷贝构造函数 90 { 91 int i; 92 memset(a,0,sizeof(a)); 93 for(i=0;i<len;i++) 94 a[i]=T.a[i]; 95 } 96 BigNum & BigNum::operator=(const BigNum &n) //重载赋值运算符,大数之间赋值运算 97 { 98 int i; 99 len=n.len; 100 memset(a,0,sizeof(a)); 101 for(i=0;i<len;i++) 102 a[i]=n.a[i]; 103 return *this; 104 } 105 istream& operator>>(istream &in,BigNum &b) 106 { 107 char ch[MAXSIZE*4]; 108 int i=-1; 109 in>>ch; 110 int L=strlen(ch); 111 int count=0,sum=0; 112 for(i=L-1;i>=0;) 113 { 114 sum=0; 115 int t=1; 116 for(int j=0;j<4&&i>=0;j++,i--,t*=10) 117 { 118 sum+=(ch[i]-'0')*t; 119 } 120 b.a[count]=sum; 121 count++; 122 } 123 b.len=count++; 124 return in; 125 } 126 ostream& operator<<(ostream& out,BigNum& b) //重载输出运算符 127 { 128 int i; 129 cout<<b.a[b.len-1]; 130 for(i=b.len-2;i>=0;i--) 131 { 132 printf("%04d",b.a[i]); 133 } 134 return out; 135 } 136 BigNum BigNum::operator+(const BigNum &T)const //两个大数之间的相加运算 137 { 138 BigNum t(*this); 139 int i,big; 140 big=T.len>len?T.len:len; 141 for(i=0;i<big;i++) 142 { 143 t.a[i]+=T.a[i]; 144 if(t.a[i]>MAXN) 145 { 146 t.a[i+1]++; 147 t.a[i]-=MAXN+1; 148 } 149 } 150 if(t.a[big]!=0) 151 t.len=big+1; 152 else t.len=big; 153 return t; 154 } 155 BigNum BigNum::operator-(const BigNum &T)const //两个大数之间的相减运算 156 { 157 int i,j,big; 158 bool flag; 159 BigNum t1,t2; 160 if(*this>T) 161 { 162 t1=*this; 163 t2=T; 164 flag=0; 165 } 166 else 167 { 168 t1=T; 169 t2=*this; 170 flag=1; 171 } 172 big=t1.len; 173 for(i=0;i<big;i++) 174 { 175 if(t1.a[i]<t2.a[i]) 176 { 177 j=i+1; 178 while(t1.a[j]==0) 179 j++; 180 t1.a[j--]--; 181 while(j>i) 182 t1.a[j--]+=MAXN; 183 t1.a[i]+=MAXN+1-t2.a[i]; 184 } 185 else t1.a[i]-=t2.a[i]; 186 } 187 t1.len=big; 188 while(t1.a[len-1]==0 && t1.len>1) 189 { 190 t1.len--; 191 big--; 192 } 193 if(flag) 194 t1.a[big-1]=0-t1.a[big-1]; 195 return t1; 196 } 197 BigNum BigNum::operator*(const BigNum &T)const //两个大数之间的相乘 198 { 199 BigNum ret; 200 int i,j,up; 201 int temp,temp1; 202 for(i=0;i<len;i++) 203 { 204 up=0; 205 for(j=0;j<T.len;j++) 206 { 207 temp=a[i]*T.a[j]+ret.a[i+j]+up; 208 if(temp>MAXN) 209 { 210 temp1=temp-temp/(MAXN+1)*(MAXN+1); 211 up=temp/(MAXN+1); 212 ret.a[i+j]=temp1; 213 } 214 else 215 { 216 up=0; 217 ret.a[i+j]=temp; 218 } 219 } 220 if(up!=0) 221 ret.a[i+j]=up; 222 } 223 ret.len=i+j; 224 while(ret.a[ret.len-1]==0 && ret.len>1)ret.len--; 225 return ret; 226 } 227 BigNum BigNum::operator/(const int &b)const //大数对一个整数进行相除运算 228 { 229 BigNum ret; 230 int i,down=0; 231 for(i=len-1;i>=0;i--) 232 { 233 ret.a[i]=(a[i]+down*(MAXN+1))/b; 234 down=a[i]+down*(MAXN+1)-ret.a[i]*b; 235 } 236 ret.len=len; 237 while(ret.a[ret.len-1]==0 && ret.len>1) 238 ret.len--; 239 return ret; 240 } 241 int BigNum::operator%(const int &b)const //大数对一个 int类型的变量进行取模 242 { 243 int i,d=0; 244 for(i=len-1;i>=0;i--) 245 d=((d*(MAXN+1))%b+a[i])%b; 246 return d; 247 } 248 BigNum BigNum::operator^(const int &n)const //大数的n次方运算 249 { 250 BigNum t,ret(1); 251 int i; 252 if(n<0)exit(-1); 253 if(n==0)return 1; 254 if(n==1)return *this; 255 int m=n; 256 while(m>1) 257 { 258 t=*this; 259 for(i=1;(i<<1)<=m;i<<=1) 260 t=t*t; 261 m-=i; 262 ret=ret*t; 263 if(m==1)ret=ret*(*this); 264 } 265 return ret; 266 } 267 bool BigNum::operator>(const BigNum &T)const //大数和另一个大数的大小比较 268 { 269 int ln; 270 if(len>T.len)return true; 271 else if(len==T.len) 272 { 273 ln=len-1; 274 while(a[ln]==T.a[ln]&&ln>=0) 275 ln--; 276 if(ln>=0 && a[ln]>T.a[ln]) 277 return true; 278 else 279 return false; 280 } 281 else 282 return false; 283 } 284 bool BigNum::operator>(const int &t)const //大数和一个int类型的变量的大小比较 285 { 286 BigNum b(t); 287 return *this>b; 288 } 289 void BigNum::print() //输出大数 290 { 291 int i; 292 printf("%d",a[len-1]); 293 for(i=len-2;i>=0;i--) 294 printf("%04d",a[i]); 295 printf(" "); 296 } 297 bool ONE(BigNum a) 298 { 299 if(a.len == 1 && a.a[0] == 1)return true; 300 else return false; 301 } 302 BigNum A,B,X,Y; 303 char str1[10010],str2[10010],str3[10010],str4[10010]; 304 305 306 int a[1010],b[1010],x[1010],y[1010]; 307 int c[1010]; 308 int main() 309 { 310 //freopen("in.txt","r",stdin); 311 //freopen("out.txt","w",stdout); 312 int T; 313 int n; 314 int iCase = 0; 315 #ifndef ONLINE_JUDGE 316 freopen("1.in","r",stdin); 317 #endif 318 scanf("%d",&T); 319 while(T--) 320 { 321 iCase++; 322 scanf("%d",&n); 323 cin>>A>>X>>B>>Y; 324 printf("Case %d: ",iCase) ; 325 A = A-1; 326 X = X-1; 327 B = B-1; 328 Y = Y-1; 329 for(int i = 0;i < n;i++) 330 { 331 if(A.a[0]%2 == 0)a[i] = 0; 332 else a[i] = 1; 333 if(B.a[0]%2 == 0)b[i] = 0; 334 else b[i] = 1; 335 if(X.a[0]%2 == 0)x[i] = 0; 336 else x[i] = 1; 337 if(Y.a[0]%2 == 0)y[i] = 0; 338 else y[i] = 1; 339 A = A/2; 340 B = B/2; 341 X = X/2; 342 Y = Y/2; 343 } 344 bool flag = false; 345 for(int k = 0;k <= n;k++) 346 { 347 x[n] = x[0]; 348 y[n] = y[0]; 349 for(int i = 0;i < n;i++) 350 { 351 x[i] = x[i+1]; 352 y[i] = y[i+1]; 353 } 354 for(int i = 0;i < n;i++) 355 { 356 if(a[i] == x[i])c[i] = 0; 357 else c[i] = 1; 358 } 359 bool fff = true; 360 for(int i = 0;i < n;i++) 361 if(b[i]^c[i] != y[i]) 362 { 363 fff = false; 364 break; 365 } 366 if(fff)flag = true; 367 if(flag)break; 368 369 } 370 if(flag)printf("Yes "); 371 else printf("No "); 372 } 373 return 0; 374 }