bzoj千題計劃310:bzoj5285: [Hnoi2018]尋寶遊戲(思惟題+哈希)

https://www.lydsy.com/JudgeOnline/problem.php?id=5285php

 

|0 和 &1 沒有影響spa

若填‘|’,記爲0,若填‘&’,記爲1code

先只考慮最後一位blog

若要求最後=1get

那麼最後一個|1 要在最後一個 &0 後面it

將n個數的最後一位拿出來構成一個01序列io

填在全部數最後一位以前的運算符也拿出來構成一個01序列class

將第n個數所在位置視爲最高位di

對於最高位來講co

若是數字序列 和 運算符序列 都是0或都是1,沒有影響

若是數字序列是0,運算符序列是1,即最後是 &0,顯然不能最終等於1,因此這種運算符序列不合法

若是數字序列是1,運算符序列是0,及最後是|1,顯然必定是1,這種運算符序列合法

若是數字序列始終等於運算符序列,由於沒有影響,因此最終開始開始的那個0,此運算符序列也不合法

因此

若是這一位要求是1,在只考慮這一位的狀況下,合法的運算符序列是 運算符的01序列<數字的01序列

同理能夠推出

若是這一位要求是0,在只考慮這一位的狀況下,合法的運算符序列是 運算符的01序列>=數字的01序列

便可以獲得這樣的條件:

設合法的運算符序列爲S,第i位的數字序列爲Ai

若p的第i位爲1,則S<Ai  ①

若p的第i位爲0,則S>=Ai ②

記①中最小的Ai爲 up,②中最大的Ai爲down

因此知足全部位的要求的S的個數=up-down

 

計算個數開始想的是高精減,題目要求取模,直接哈希便可

 

#include<cstdio>
#include<algorithm>

#define N 5001

using namespace std;

const int mod=1e9+7;

int bit[N];

char s[N];
int has[N];

int sa[N],now[N];

int main()
{
    int n,m,q;
    scanf("%d%d%d",&n,&m,&q);
    bit[0]=1;
    for(int i=1;i<=n;++i) 
    {
        bit[i]=bit[i-1]<<1;
        bit[i]-=bit[i]>=mod ? mod : 0;
    }
    for(int i=1;i<=m;++i) sa[i]=i;
    int c[2];
    for(int i=1;i<=n;++i)
    {
        c[1]=c[0]=0;
        scanf("%s",s+1);
        for(int j=1;j<=m;++j)
        {
            has[j]=has[j]+(s[j]-'0')*bit[i-1];
            has[j]-=has[j]>=mod ? mod : 0;
            c[s[j]-'0']++;
        }
        c[1]+=c[0];
        for(int j=m;j;--j) now[c[s[sa[j]]-'0']--]=sa[j];
        swap(sa,now);
    }
    int up,down;
    for(int t=1;t<=q;++t)
    {
        up=m+1; down=0;
        scanf("%s",s+1);
        for(int i=1;i<=m && up==m+1;++i)
            if(s[sa[i]]-'0') up=i;
        for(int i=m;i && !down;--i)
            if(!(s[sa[i]]-'0')) down=i;
        if(up<down) 
        {
            puts("0");
            continue;
        }
        up= up==m+1 ? bit[n] : has[sa[up]];
        down= !down ? 0 : has[sa[down]];
        printf("%d\n",(up-down+mod)%mod);
    }
}
相關文章
相關標籤/搜索