zoukankan      html  css  js  c++  java
  • [bzoj5285][Hnoi2018]寻宝游戏——思维+排序

    题目大意:

    给定n个m位的二进制数,在每一个数前面补上一个(lor)(land),最前面补上一个0,每次询问最后运算结果为r的方案数为多少。

    思路 :

    感觉MYY出的题就是不一样。
    位数很多,所以应该要想到对于每一位单独考虑。
    对于单独每一位,考虑每一个运算符这一位上的影响,不难发现总共有四种情况:(land 1, land 0, lor 1, lor 0),其中(land 1,lor 0)对最后的结果不会产生影响,于是我们发现(land 0)会使目前的结果为0,(lor 1)会使目前的结果为1,并且每一次的运算独立,和之前的结果并没有任何关系。
    于是可以进一步得到,如果最后的结果要为1,那么最后一个有效的运算应该是(lor 1),如果是0,则最后一个有效的运算应该是(land 0)
    于是我们把操作序列的(land)看作1,(lor)看作0,并反转。然后将每一位的序列给从后往前提出来,不难发现当这一位的序列(>)opt的时候,这一位的结果为1,反之则为0。
    于是我们只要对每一位的操作序列排序就好了。

    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define MREP(i,x) for(int i=beg[x],v;v=to[i],i;i=las[i])
    #define debug(x) cout<<#x<<"="<<x<<endl
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
        freopen("bzoj5285.in","r",stdin);
        freopen("bzoj5285.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
        T __=0,mul=1; char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')mul=-1;
            ch=getchar();
        }
        while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
        _=__*mul;
    }
    
    const int maxn=1000+10;
    const int maxm=5000+10;
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    int n,m,q,rank[maxm];
    ll p2[maxn],sum[maxm];
    bool t[maxm];
    struct node{
        int id;
        bool num[maxn];
        bool operator < (const node & tt) const {
            REP(i,1,n)if(num[i]<tt.num[i])return 1;
            else if(num[i]>tt.num[i])return 0;
            return 0;
        }
    }a[maxm];
    
    void init(){
        read(n); read(m); read(q);
        p2[0]=1;
        REP(i,1,n)p2[i]=p2[i-1]*2%mod;
        REP(i,1,n){
            char ch=getchar();
            int cnt=0;
            while(!isdigit(ch))ch=getchar();
            while(isdigit(ch))a[++cnt].num[n-i+1]=ch^'0',ch=getchar();
        }
        REP(i,1,m)a[i].id=i;
        sort(a+1,a+m+1);
        REP(i,1,m)rank[a[i].id]=i;
        //REP(i,1,m)printf("%d
    ",rank[i]);
        /*REP(i,1,m){
            //printf("%d
    ",a[i].id);
            REP(j,1,n)printf("%d",a[i].num[j]);
            putchar('
    ');
        }*/
    }
    
    void work(){
        REP(i,1,n)a[m+1].num[i]=1;
        REP(i,1,m+1)REP(j,1,n)if(a[i].num[j])
            sum[i]=(sum[i]+p2[n-j])%mod;
        ++sum[m+1];
        REP(ca,1,q){
            char ch=getchar();
            int cnt=0,L=0,R=m+1;
            while(!isdigit(ch))ch=getchar();
            while(isdigit(ch))t[++cnt]=ch^'0',ch=getchar();
            REP(i,1,m)if(t[i])R=min(R,rank[i]);
            else L=max(L,rank[i]);
            //cout<<L<<" "<<R<<endl;
            if(L>R)printf("0
    ");
            else printf("%lld
    ",(sum[R]-sum[L]+mod)%mod);
            /*REP(i,1,n)cout<<t[i];
              cout<<endl;*/
        }
    }
    
    int main(){
    //	File();
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    阅读笔记2
    阅读笔记1
    学习进度条
    第二阶段冲刺第七天站立会议
    第二阶段冲刺第六天站立会议
    第二阶段冲刺第五天站立会议
    阅读笔记4
    第二阶段冲刺第四天站立会议
    第一阶段意见评论
    第12周学习进度总结
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10072827.html
Copyright © 2011-2022 走看看