位運算

我一直沒有更新,緣由不解釋。個人luogu有這一篇,我搬運過來哈。c++

先感謝李煜東老師的辛勤勞動,我是借鑑他的成果。 位運算共有4種,它們是與或非和異或廢話git

十進制的數不能參與運算,在計算機中是二進制,若是直接對其運算就比十進制塊不少。因此說位運算最快,而後是加減,接着是乘除,最慢的是取模,慢的一匹你們先體驗一把位運算,打開手機計算器的科學計數法,而後調成二進制。。。數組

好,與指的是按照二進制位的兩個數字,兩位都是1就是1,不然爲0,或就是按照二進制位兩位有一位是1就爲1,兩個數位都是0纔是0,非就是把每一位都取反,異或是兩位相同爲0,不一樣爲1。須要注意的是兩個數比較時不足位按0計算,直到兩個數位數相同。優化

左移就是直接把每一位都向左移,右移也是這樣的。隨意 來舉個例子5等於二進制下的101(這個確定會啊),左移兩位就是10100(低位是0補足),天然是十進制下的20啦!ui

左移就是乘二右移就是除二,哦咱們好像能夠用這個優化乘二啊!還有更神奇的事情!n<<1就是乘二,n<<3就是乘8啊,那麼加起來不就是乘十了嗎?這真是激動人心的發現 固然同理有的減法也能夠用^來優化,或能夠用來判斷奇數:好比11的二進制是1011,(1011&1)=(1011&0001)=(0001)返回了1! 哇太強了,之後能夠用(x&1)判斷是否是奇數了,若是用x%2的後果就是x不停的減二。。。一直減到剩下1或者0。spa

順便講一下lowbit運算,這個可吊了。lowbit的定義是整數在二進制下最低位的1及其後邊的全部0,lowbit(n)=n&(-n) 這波廢話其實意思是說找到最右的1構成的數,好比lowbit(14)=1110,那麼lowbit(n)就是2啊!這個詳見樹狀數組。code

狀態壓縮就是將一個長度爲m的bool數組換成一個用二進制數存貯的方法。下列是狀態壓縮的經常使用表達式: 1,取出n的第k位 (n>>k)&1 就是把n刪掉幾位或1,簡單吧get

2,取出n的後k位 n&((1<<k)-1) 這個我也不怎麼會it

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;
}
相關文章
相關標籤/搜索