$ [HNOI / AHOI2018] $宝探し

\([HNOI / AHOI2018] \ ) 宝探し

良い質問を考えます。

それぞれ引き出さ組成\(Mの\)長の\(N- \)進数。

操作を考えてみましょう\(01 \)シーケンス、\((\ LOR \ TO0、\土地\ TO1)\)

それは最初について観察した後\(J \)結果のビットが\(1 \)が最後である\(\ lor1 \)操作の位置になければならない(\ land0 \)\後。

変換が必要とどのようなものです\(X \ GT \)オペレーティング文字列を。

逆に、\(Jは\)である\(0 \)最後の既知の場合と同様に、\(\ land0 \)操作の位置になければならない(\ lor1 \)\後。

変換が必要とどのようなものです\(X \当量\)オペレーティング文字列を。

バイナリ列の配列のうち将軍、動作は、上限および下限を見つけるために減算します。

注意すべきいくつかの詳細は、例えば、元の文字列から最上位ビットのバイナリストリング、ある\(1 \)番目は最初に\(N \)ヶ月。

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    int f=1,w=0;char x=0;
    while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
    while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
    return w*f;
}
const int p=1e9+7;
const int N=5e3+10;
string S[N];
int n,m,M[N],Rnk[N],Q,Sum[N];
struct Number
{
    int x[N/5+1],Id;
    inline bool operator < (const Number &y) const
        {
            for(int i=1;i<=n;i++)
                if(x[i]!=y.x[i]) return x[i]<y.x[i];
            return 0;
        }
} t[N];
signed main(){
#ifndef ONLINE_JUDGE
    freopen("A.in","r",stdin);//Ans=6
#endif
    n=read(),m=read();Q=read();M[0]=1;
    for(int i=1;i<=n;i++) M[i]=(M[i-1]*2)%p;
    for(int i=1;i<=n;i++) cin>>S[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            t[j].x[n-i+1]=S[i][j-1]-'0';
    for(int i=1;i<=m;i++) t[i].Id=i;
    sort(t+1,t+m+1);
    for(int i=1;i<=m;i++) Rnk[t[i].Id]=i;
    for(int i=1;i<=n;i++) t[m+1].x[i]=1;
    for(int i=1;i<=m+1;i++)
        for(int j=1;j<=n;j++)
            if(t[i].x[j]) Sum[i]=(Sum[i]+M[n-j])%p;
    Sum[m+1]++;
    while(Q--)
    {
        int B=0,E=m+1;string X;cin>>X;
        for(int i=1;i<=m;i++) if((X[i-1]-'0')) E=min(E,Rnk[i]);
        for(int i=1;i<=m;i++) if(!(X[i-1]-'0')) B=max(B,Rnk[i]);
        if(B>E) {puts("0");continue;}
        printf("%lld\n",(Sum[E]-Sum[B]+p)%p);
    }
}

おすすめ

転載: www.cnblogs.com/wo-shi-zhen-de-cai/p/11741221.html