基础算法知识点小结
目录
bit指1个0或者1 二进制[begin{array}{c}{Large 117=(1110101)_2}hspace{1cm}{tinytext{最低位(0)}}hspace{0.6cm}{tinytext{最高位(6)}}end{array}] 十六进制表示以(0x)开头后面接十六进制数,如(0x75)表示十六进制数75,即((75)_6=117) 表
注: 最好能够记得,然后随便给你一个十六进制数,你能一秒内写出它的二进制位,十六进制的好处在于,十进制无法凸显二进制中的每一位,而十六进制的一位可以表现二进制中的8位,虽然考试不考,但是肯定对你有帮助,而且也可以锻炼你的记忆能力,尽管我现在都还记不得。 补码和反码采取补码的类型满足(-x=sim x+1) 采取反码的类型满足(-x=sim x) 注:c++通常采用补码 无符号整型和有符号整型以下对第n位而言
注释 ({tinyboxed{1}}:) (-2^n)等价于0,因为0的取反+1为0,而(-2^n)取反+1也为0,而这也解释为什么溢出了是对(2^{n-1})取模。 memset表达式[memset(a,b,sizeof(a))] 解释
位运算(讲解顺序按算术优先级排序) (sim)(非)表达式:(sim a)解释对a的二进制位下每一位进行取反操作,即0变为1,1变为0,如3为二进制数(~(101)_2=(010)_2) 解释对a的二进制位下每一位取反,即 (<<,>>)(左移,右移)表达式(a<<b,a>>b) 解释
(&;)(与)表达式(:a&;b)解释a,b二进制位下,每一位对应二进制位同为1才为1,否则为0,如((10011)_2&;(10000)_2=(10000)_2) $$(异或)表达式:(awedge b)解释
(|)(或)表达式:(a|b)解释对于a,b每一位二进制位对应运算,只要有1就为1,如((10011)_2wedge(10000)_2=(10011)_2) 与或非通性运算中可以拆开每一位独自运算,这样对于二进制运算的题目,我们可以对于每一位独自运算,这样会更加好做。 快速幂[注:以下的ll均表示long long] 二分快速幂原理:(x^y=(x^{y/2})^2times begin{cases}x(yintext{奇数})1(yintext{偶数})end{cases})代码实现:int pow(int x,int y,int yyb){ if(!y)return 1; int ans(pow(x,y>>1,yyb)); return ans*ans%yyb*((y&1)?x:1)%yyb; } 二进制(拆分)幂原理:({Large x^y=x^{c_{k-1}2^{k-1}+c_{k-2}2^{k-2}+...+c_02^0}})代码实现:int pow(int x,int yyb){ int ans(1%yyb);while(y){ if(y&1)ans=(ll)ans*x%yyb; x=x*x%yyb,y>>=1; }return ans; 练习 64位乘法问题求(atimes b %yyb),其中,(a,yybleq 10^{18}) 根号乘原理[atimes b% yyb=(atimessqrt{b}% yybtimes sqrt{b}% yyb+atimes (b-sqrt{b}times sqrt{b})%yyb)%yyb] 代码实现此法已萎,有兴趣者自我娱乐 龟速乘原理[atimes b% yyb=atimes (c_{k-1}2^{k-1}+c_{k-2}2^{k-2}+...+c_02^0)%yyb=ac_{k-1}2^{k-1}% yyb+ac_{k-2}2^{k-2}% yyb+...+ac_02^0%yyb] 参考代码ll mult(ll a,ll b,ll p){ ll ans(0);while(b){ if(b&1)(ans+=a)%=p; (a<<=1)%=p,b>>=1; }return ans; } 快速乘原理[atimes b%yyb=atimes b-([atimes b/yyb]times yyb] 代码实现ll mult(ll a,ll p){ ll ans(a*b-(ll)((lb)a*b/p)*p); if(ans<0)ans+=p;return ans; } 证明: 设(x=atimes b,y=[atimes b/yyb]times yyb,xequiv x'(mod 2^{63}),yequiv y'(mod 2^{63})) 显然有(x-yequiv x'-y'(mod 2^{63})equiv atimes b%yyb),而(yyb<2^{63}),于是有 ((x-y)% 2^{63}=atimes b%yyb),得证 练习 二进制压缩标志数据范围小 做法用一个数字的二进制位表示bool变量的0or1,如开了个(bool a[31]),用b存储,其中b二进制第0位等价与(a[0]),第一位等价与(a[1]),...以此类推 常用操作
练习: 最短Hamilton路径 成对变换定义(nwedge1=begin{cases}n+1(nintext{偶数})n-1(nintext{奇数})end{cases}) 于是称一对相邻的奇数偶数(a,b(b-a=1))为成对变换,而且具有性质(awedge 1=b,bwedge1=a) lowbit定义[lowbit(x)=x&;-x=text{x最后的一位1以及后面的0组成的数(如$lowbit((1100100)_2)=100$)}] 应用快速查找一个二进制数x的每一个1所在的位置 做法:
求证: (2^0%37,2^1%37,2^{36}% 37)互不相同 证明: 注意到37是一个质数,且与2互质,故满足费马小定理,有(2^{36}equiv 1(mod 37)) 于是易知余数循环节为36,故36以内的数互不相同
参考代码 void prepare(){ for(int i(0);i<37;++i) to[(1<<i)%37]=i; } void work(int n){ while(n){ printf("%d ",to[lowbit(n)%37]); n-=lowbit(n); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |