位运算
Posted aserrrre
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位运算相关的知识,希望对你有一定的参考价值。
我一直没有更新,原因不解释。我的luogu有这一篇,我搬运过来哈。
先感谢李煜东老师的辛勤劳动,我是借鉴他的成果。 位运算共有4种,它们是与或非和异或废话
十进制的数不能参与运算,在计算机中是二进制,如果直接对其运算就比十进制块很多。所以说位运算最快,然后是加减,接着是乘除,最慢的是取模,慢的一匹大家先体验一把位运算,打开手机计算器的科学计数法,然后调成二进制。。。
好,与指的是按照二进制位的两个数字,两位都是1就是1,否则为0,或就是按照二进制位两位有一位是1就为1,两个数位都是0才是0,非就是把每一位都取反,异或是两位相同为0,不同为1。需要注意的是两个数比较时不足位按0计算,直到两个数位数相同。
左移就是直接把每一位都向左移,右移也是这样的。随意 来举个例子5等于二进制下的101(这个肯定会啊),左移两位就是10100(低位是0补足),自然是十进制下的20啦!
左移就是乘二右移就是除二,哦我们好像可以用这个优化乘二啊!还有更神奇的事情!n<<1就是乘二,n<<3就是乘8啊,那么加起来不就是乘十了吗?这真是激动人心的发现 当然同理有的减法也可以用^来优化,或可以用来判断奇数:比如11的二进制是1011,(1011&1)=(1011&0001)=(0001)返回了1! 哇太强了,以后可以用(x&1)判断是不是奇数了,如果用x%2的后果就是x不停的减二。。。一直减到剩下1或者0。
顺便讲一下lowbit运算,这个可吊了。lowbit的定义是整数在二进制下最低位的1及其后边的所有0,lowbit(n)=n&(-n) 这波废话其实意思是说找到最右的1构成的数,比如lowbit(14)=1110,那么lowbit(n)就是2啊!这个详见树状数组。
状态压缩就是将一个长度为m的bool数组换成一个用二进制数存贮的方法。下列是状态压缩的常用表达式: 1,取出n的第k位 (n>>k)&1 就是把n删掉几位或1,简单吧
2,取出n的后k位 n&((1<<k)-1) 这个我也不怎么会
3.把n的第k位赋1 n|(1<<k) 就是制造一个数是2的k次方才能和n进行运算啊,同理有 n^(1<<k) 和 n&(~(1<<k))这个是第k位赋0
接下来是位运算实战!!!大佬勿喷
1,位运算加速快速幂
#define int long long
inline int quickpower(int a,int b,int p){
register int ans=1;
for (;b;b>>=1){
if (b&1) ans=ans*a%p;
a=a*a%p;
}return ans;
}
2,最短曼哈顿路径
int f[1<<20][20];
inline int hamilton(int n,int weight[20][20]){
memset(f,0x3fsizeof(f));
f[1][0]=0;
for (register int i=1;i<=1<<n;++i)
for (register int j=0;j<n;++j)
if (i<<j&1)
for (register int k=0;k<n;k++)
if ((i^1<<j)>>k&1)
f[i][j]=min(f[i][j],f[i^1<<j][k]+weight[k][j]);
return f[(1<<n)-1][n-1];
}
我们到了主题,P3901 这道题一开始把我看得一脸懵逼,最后看懂了,原来是要求出是不是每个数字都不同啊!这是我的题解,自然还能优化,不再细说了。
#include<bits/stdc++.h>
using namespace std;
int a[100001],n,q;
bool b[100001];
inline int read(){
register int x=0;
register char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c))
x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
int main(){register bool flag=false;
n=read(),q=read();
for (register int i=1;i<=n;i++)
a[i]=read();
for (register int i=1,l,r;i<=q;i++){
l=read(),r=read(),flag=false;
memset(b,false,sizeof(b));
for (register int j=l;j<=r;j++)
if (b[a[j]]){
flag=true,puts("No");
break;
}
else b[a[j]]=1;
if (!flag) puts("Yes");
}
return 0;
}
以上是关于位运算的主要内容,如果未能解决你的问题,请参考以下文章