题解 洛谷 P4424 【[HNOI/AHOI2018]寻宝游戏】

不难发现 (vee 1)(wedge 0) 是会影响到最终结果的,相当于赋值操作,而 (wedge 1)(vee 0) 是无法对结果产生影响的。当某一位最终的结果是 (1) 时,最后一个能产生影响的操作必须是 (vee 1),当最终的结果是 (0) 时,最后一个能产生影响的操作必须是 (wedge 0)

(n) 个二进制串,对每一位分别来进行考虑,得到 (m) 个长度为 (n) 的二进制串,每一位都对应一个二进制串。把 (veewedge) 的运算序列也看作一个二进制串,(vee) 看作 (0)(wedge) 看作 (1),根据刚才的性质得,若第 (i) 位的最终结果为 (1),则第 (i) 位对应的二进制串要大于运算序列对应的二进制串,若第 (i) 位的最终结果为 (0),则第 (i) 位对应的二进制串要小于等于运算序列对应的二进制串。

因此先将 (m) 个二进制串排序后,并处理出其对应的权值。对于每个询问串,通过每一位的限制得出运算序列的取值范围,作差即可求解。

同时还需在边界上加上极大值和极小值,因为两个限制分别是大于和小于等于,所以极大值还需特殊处理,让其权值再加上 (1)

#include<bits/stdc++.h>
#define maxn 5010
#define p 1000000007
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,m,q;
int rnk[maxn];
ll pw[maxn],val[maxn];
char str[maxn];
struct node
{
    int s[maxn];
    int id;
}t[maxn];
bool cmp(const node &a,const node &b)
{
    for(int i=n;i;--i)
        if(a.s[i]!=b.s[i])
            return a.s[i]<b.s[i];
    return 0;
}
int main()
{
    read(n),read(m),read(q),pw[0]=1;
    for(int i=1;i<=n;++i) pw[i]=pw[i-1]*2%p;
    for(int i=1;i<=n;++i)
    {
        scanf("%s",str+1);
        for(int j=1;j<=m;++j) t[j].s[i]=str[j]-'0';
    }
    for(int i=1;i<=n;++i) t[m+1].s[i]=1;
    for(int i=1;i<=m+1;++i) t[i].id=i;
    sort(t+1,t+m+1,cmp),val[m+1]=1;
    for(int i=1;i<=m+1;++i)
    {
        rnk[t[i].id]=i;
        for(int j=1;j<=n;++j)
            val[i]=(val[i]+pw[j-1]*t[i].s[j])%p;
    }
    while(q--)
    {
        int l=0,r=m+1;
        scanf("%s",str+1);
        for(int i=1;i<=m;++i)
        {
            if(str[i]-'0') r=min(r,rnk[i]);
            else l=max(l,rnk[i]);
        }
        printf("%lld
",l>r?0:(val[r]-val[l]+p)%p);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lhm-/p/13598831.html