zoukankan      html  css  js  c++  java
  • hdu 4759 Poker Shuffle(规律,大数,位)

    很神奇的一道题。

    参考:http://www.cnblogs.com/kuangbin/p/3346037.html

    题意:


    题目意思很简单。

    就是洗牌,抽出奇数和偶数,要么奇数放前面,要么偶数放前面。 总共2^N张牌。需要问的是,给了A X B Y  问经过若干洗牌后,第A个位置是X,第B个位置是Y 是不是可能的。 

     

    题目给的牌编号是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 

     ”

    问题1:为什么是相同的数?

     因为对k个数的操作要么是第一种洗牌,要么是第二种洗牌,也就是说对每个数最高位异或的数(0或1)是一样的。而这个异或操作会随该位的移动而移动,累积。

    问题2:为什么只需要枚举n次?

    因为2^n 只有n位,循环右移n位之后变为原数。

    PS:

    1、有点压缩的味道。

    2、a[0]为低位,a[n]为高位。

      1 #pragma comment(linker, "/STACK:1024000000,1024000000")
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <vector>
      7 #include <queue>
      8 #include <set>
      9 #include <map>
     10 #include <string>
     11 #include <math.h>
     12 #include <stdlib.h>
     13 #include <time.h>
     14 using namespace std;
     15 
     16 /*
     17  * 完全大数模板
     18  * 输出cin>>a
     19  * 输出a.print();
     20  * 注意这个输入不能自动去掉前导0的,可以先读入到char数组,去掉前导0,再用构造函数。
     21  */
     22 #define MAXN 9999
     23 #define MAXSIZE 1010
     24 #define DLEN 4
     25 
     26 class BigNum
     27 {
     28 public:
     29     int a[500];  //可以控制大数的位数
     30     int len;
     31 public:
     32     BigNum(){len=1;memset(a,0,sizeof(a));}  //构造函数
     33     BigNum(const int);     //将一个int类型的变量转化成大数
     34     BigNum(const char*);   //将一个字符串类型的变量转化为大数
     35     BigNum(const BigNum &); //拷贝构造函数
     36     BigNum &operator=(const BigNum &); //重载赋值运算符,大数之间进行赋值运算
     37     friend istream& operator>>(istream&,BigNum&); //重载输入运算符
     38     friend ostream& operator<<(ostream&,BigNum&); //重载输出运算符
     39 
     40     BigNum operator+(const BigNum &)const;  //重载加法运算符,两个大数之间的相加运算
     41     BigNum operator-(const BigNum &)const;  //重载减法运算符,两个大数之间的相减运算
     42     BigNum operator-(const int &)const;
     43     BigNum operator*(const BigNum &)const;  //重载乘法运算符,两个大数之间的相乘运算
     44     BigNum operator/(const int &)const;     //重载除法运算符,大数对一个整数进行相除运算
     45 
     46     BigNum operator^(const int &)const;     //大数的n次方运算
     47     int operator%(const int &)const;        //大数对一个int类型的变量进行取模运算
     48     bool operator>(const BigNum &T)const;   //大数和另一个大数的大小比较
     49     bool operator>(const int &t)const;      //大数和一个int类型的变量的大小比较
     50 
     51     void print();        //输出大数
     52 };
     53 BigNum::BigNum(const int b)   //将一个int类型的变量转化为大数
     54 {
     55     int c,d=b;
     56     len=0;
     57     memset(a,0,sizeof(a));
     58     while(d>MAXN)
     59     {
     60         c=d-(d/(MAXN+1))*(MAXN+1);
     61         d=d/(MAXN+1);
     62         a[len++]=c;
     63     }
     64     a[len++]=d;
     65 }
     66 BigNum::BigNum(const char *s)  //将一个字符串类型的变量转化为大数
     67 {
     68     int t,k,index,L,i;
     69     memset(a,0,sizeof(a));
     70     L=strlen(s);
     71     len=L/DLEN;
     72     if(L%DLEN)len++;
     73     index=0;
     74     for(i=L-1;i>=0;i-=DLEN)
     75     {
     76         t=0;
     77         k=i-DLEN+1;
     78         if(k<0)k=0;
     79         for(int j=k;j<=i;j++)
     80             t=t*10+s[j]-'0';
     81         a[index++]=t;
     82     }
     83 }
     84 BigNum::BigNum(const BigNum &T):len(T.len)  //拷贝构造函数
     85 {
     86     int i;
     87     memset(a,0,sizeof(a));
     88     for(i=0;i<len;i++)
     89         a[i]=T.a[i];
     90 }
     91 BigNum & BigNum::operator=(const BigNum &n)  //重载赋值运算符,大数之间赋值运算
     92 {
     93     int i;
     94     len=n.len;
     95     memset(a,0,sizeof(a));
     96     for(i=0;i<len;i++)
     97         a[i]=n.a[i];
     98     return *this;
     99 }
    100 istream& operator>>(istream &in,BigNum &b)
    101 {
    102     char ch[MAXSIZE*4];
    103     int i=-1;
    104     in>>ch;
    105     int L=strlen(ch);
    106     int count=0,sum=0;
    107     for(i=L-1;i>=0;)
    108     {
    109         sum=0;
    110         int t=1;
    111         for(int j=0;j<4&&i>=0;j++,i--,t*=10)
    112         {
    113             sum+=(ch[i]-'0')*t;
    114         }
    115         b.a[count]=sum;
    116         count++;
    117     }
    118     b.len=count++;
    119     return in;
    120 }
    121 ostream& operator<<(ostream& out,BigNum& b)  //重载输出运算符
    122 {
    123     int i;
    124     cout<<b.a[b.len-1];
    125     for(i=b.len-2;i>=0;i--)
    126     {
    127         printf("%04d",b.a[i]);
    128     }
    129     return out;
    130 }
    131 BigNum BigNum::operator+(const BigNum &T)const   //两个大数之间的相加运算
    132 {
    133     BigNum t(*this);
    134     int i,big;
    135     big=T.len>len?T.len:len;
    136     for(i=0;i<big;i++)
    137     {
    138         t.a[i]+=T.a[i];
    139         if(t.a[i]>MAXN)
    140         {
    141             t.a[i+1]++;
    142             t.a[i]-=MAXN+1;
    143         }
    144     }
    145     if(t.a[big]!=0)
    146        t.len=big+1;
    147     else t.len=big;
    148     return t;
    149 }
    150 //BigNum BigNum::operator-(const BigNum&) const
    151 
    152 BigNum BigNum::operator-(const BigNum &T)const  //两个大数之间的相减运算
    153 {
    154     int i,j,big;
    155     bool flag;
    156     BigNum t1,t2;
    157     if(*this>T)
    158     {
    159         t1=*this;
    160         t2=T;
    161         flag=0;
    162     }
    163     else
    164     {
    165         t1=T;
    166         t2=*this;
    167         flag=1;
    168     }
    169     big=t1.len;
    170     for(i=0;i<big;i++)
    171     {
    172         if(t1.a[i]<t2.a[i])
    173         {
    174             j=i+1;
    175             while(t1.a[j]==0)
    176                 j++;
    177             t1.a[j--]--;
    178             while(j>i)
    179                 t1.a[j--]+=MAXN;
    180             t1.a[i]+=MAXN+1-t2.a[i];
    181         }
    182         else t1.a[i]-=t2.a[i];
    183     }
    184     t1.len=big;
    185     while(t1.a[len-1]==0 && t1.len>1)
    186     {
    187         t1.len--;
    188         big--;
    189     }
    190     if(flag)
    191         t1.a[big-1]=0-t1.a[big-1];
    192     return t1;
    193 }
    194 
    195 BigNum BigNum::operator-(const int &b)const  //大数-int
    196 {
    197     BigNum B(b);
    198     return *this - B;
    199 }
    200 
    201 BigNum BigNum::operator*(const BigNum &T)const  //两个大数之间的相乘
    202 {
    203     BigNum ret;
    204     int i,j,up;
    205     int temp,temp1;
    206     for(i=0;i<len;i++)
    207     {
    208         up=0;
    209         for(j=0;j<T.len;j++)
    210         {
    211             temp=a[i]*T.a[j]+ret.a[i+j]+up;
    212             if(temp>MAXN)
    213             {
    214                 temp1=temp-temp/(MAXN+1)*(MAXN+1);
    215                 up=temp/(MAXN+1);
    216                 ret.a[i+j]=temp1;
    217             }
    218             else
    219             {
    220                 up=0;
    221                 ret.a[i+j]=temp;
    222             }
    223         }
    224         if(up!=0)
    225            ret.a[i+j]=up;
    226     }
    227     ret.len=i+j;
    228     while(ret.a[ret.len-1]==0 && ret.len>1)ret.len--;
    229     return ret;
    230 }
    231 BigNum BigNum::operator/(const int &b)const  //大数对一个整数进行相除运算
    232 {
    233     BigNum ret;
    234     int i,down=0;
    235     for(i=len-1;i>=0;i--)
    236     {
    237         ret.a[i]=(a[i]+down*(MAXN+1))/b;
    238         down=a[i]+down*(MAXN+1)-ret.a[i]*b;
    239     }
    240     ret.len=len;
    241     while(ret.a[ret.len-1]==0 && ret.len>1)
    242         ret.len--;
    243     return ret;
    244 }
    245 int BigNum::operator%(const int &b)const   //大数对一个 int类型的变量进行取模
    246 {
    247     int i,d=0;
    248     for(i=len-1;i>=0;i--)
    249         d=((d*(MAXN+1))%b+a[i])%b;
    250     return d;
    251 }
    252 BigNum BigNum::operator^(const int &n)const  //大数的n次方运算
    253 {
    254     BigNum t,ret(1);
    255     int i;
    256     if(n<0)exit(-1);
    257     if(n==0)return 1;
    258     if(n==1)return *this;
    259     int m=n;
    260     while(m>1)
    261     {
    262         t=*this;
    263         for(i=1;(i<<1)<=m;i<<=1)
    264            t=t*t;
    265         m-=i;
    266         ret=ret*t;
    267         if(m==1)ret=ret*(*this);
    268     }
    269     return ret;
    270 }
    271 bool BigNum::operator>(const BigNum &T)const    //大数和另一个大数的大小比较
    272 {
    273     int ln;
    274     if(len>T.len)return true;
    275     else if(len==T.len)
    276     {
    277         ln=len-1;
    278         while(a[ln]==T.a[ln]&&ln>=0)
    279           ln--;
    280         if(ln>=0 && a[ln]>T.a[ln])
    281            return true;
    282         else
    283            return false;
    284     }
    285     else
    286        return false;
    287 }
    288 bool BigNum::operator>(const int &t)const  //大数和一个int类型的变量的大小比较
    289 {
    290     BigNum b(t);
    291     return *this>b;
    292 }
    293 void BigNum::print()   //输出大数
    294 {
    295     int i;
    296     printf("%d",a[len-1]);
    297     for(i=len-2;i>=0;i--)
    298       printf("%04d",a[i]);
    299     printf(" ");
    300 }
    301 bool ONE(BigNum a)
    302 {
    303     if(a.len == 1 && a.a[0] == 1)return true;
    304     else return false;
    305 }
    306 
    307 BigNum A,B,X,Y;
    308 int a[1010], b[1010], x[1010], y[1010], c[1010], d[1010];
    309 
    310 int main()
    311 {
    312     int t, n;
    313     scanf("%d",&t);
    314     for(int cas=1; cas<=t; ++cas)
    315     {
    316         scanf("%d",&n);
    317         cin >> A >> X >> B >> Y;
    318         A = A - 1;
    319         B = B - 1;
    320         X = X - 1;
    321         Y = Y - 1;
    322         for(int i=0; i<n; i++)
    323         {
    324             if(A.a[0]%2==0) a[i] = 0;
    325             else a[i] = 1;
    326             if(B.a[0]%2==0) b[i] = 0;
    327             else b[i] = 1;
    328             if(X.a[0]%2==0) x[i] = 0;
    329             else x[i] = 1;
    330             if(Y.a[0]%2==0) y[i] = 0;
    331             else y[i] = 1;
    332 
    333             A = A / 2;
    334             B = B / 2;
    335             X = X / 2;
    336             Y = Y / 2;
    337         }
    338         int flag1 = 0;
    339         for(int i=0; i<n; i++)
    340         {
    341             int flag2 = 0;
    342             for(int j=0; j<n; j++)
    343             {
    344                 c[j] = x[(j+i)%n] ^ a[j];
    345                 d[j] = y[(j+i)%n] ^ b[j];
    346                 if(c[j]!=d[j])
    347                 {
    348                     flag2 = 1;
    349                     break;
    350                 }
    351             }
    352             if(flag2==0) {flag1 = 1break;}
    353         }
    354         if(flag1==1) printf("Case %d: Yes ",cas);
    355         else if(flag1==0) printf("Case %d: No ",cas);
    356 
    357     }
    358     return 0;
    359 }
    View Code
  • 相关阅读:
    vue项目webpack配置terser-webpack-plugin 去掉项目中多余的debugger
    difference between count(1) and count(*)
    为什么PostgreSQL WAL归档很慢
    mysql_reset_connection()
    Oracle使用audit跟踪登录失败的连接信息
    .NET Standard 版本
    ASP.NET Web API版本
    我是如何用go-zero 实现一个中台系统的
    JAVA中文件写入的6种方法
    MySql 常用语句
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3571919.html
Copyright © 2011-2022 走看看