zoukankan      html  css  js  c++  java
  • BZOJ5285: [Hnoi2018]寻宝游戏

    【传送门:BZOJ5285


    简要题意:

      懒惰成性

      PS:and和or运算符在这道题里面是相同优先级的


    题解:

      显然&1或者|0都是没有意义的操作

      我们把运算符也当成01,&表示1,|表示0

      这样子对于一个运算式,就可以转成一个01字符串了

      我们可以一列一列处理值

      若某一列的最终值为1,则需要满足最后一个|1的位置出现在最后一个&0的位置后面

      为0,则需要满足最后一个&0的位置要出现在最后一个|1的位置后面

      可以发现,使结果为1的运算串为所有字典序小于当前位构成的01串的01串

      那么结果为0的运算串就是除了结果为1的运算串之外的01串

      那么我们就能得到每一列运算串的范围

      然后我们只要取出所有列构成的运算串的范围的公共部分就行了

      因为如果直接将01串转成数字太大了,所以如果要比较两个01串的大小就要用基数排序来确定顺序,从而确定大小


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    char st[5100];
    LL pw[1100],Mod=1e9+7,to1[5100];
    int Rank[5100],cnt[2],tt[5100];
    int main()
    {
        int n,m,q;
        scanf("%d%d%d",&n,&m,&q);
        pw[1]=1;
        for(int i=2;i<=n+1;i++) pw[i]=(pw[i-1]<<1)%Mod;
        for(int i=1;i<=m;i++) Rank[i]=i;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",st+1);
            cnt[0]=cnt[1]=0;
            for(int j=1;j<=m;j++)
            {
                to1[j]=(to1[j]+LL(st[j]-'0')*pw[i])%Mod;
                cnt[st[j]-'0']++;
            }
            cnt[1]+=cnt[0];
            for(int j=m;j>=1;j--) tt[cnt[st[Rank[j]]-'0']--]=Rank[j];
            for(int j=1;j<=m;j++) swap(tt[j],Rank[j]);
        }
        reverse(Rank+1,Rank+m+1);
        while(q--)
        {
            scanf("%s",st+1);
            int l=0,r=m+1;
            for(int i=m;i>=1;i--)
            {
                if(st[Rank[i]]=='1')
                {
                    r=i;break;
                }
            }
            for(int i=1;i<=m;i++)
            {
                if(st[Rank[i]]=='0')
                {
                    l=i;break;
                }
            }
            if(l==0) printf("%lld
    ",to1[Rank[r]]);
            else if(r==m+1) printf("%lld
    ",(pw[n+1]-to1[Rank[l]]+Mod)%Mod);
            else if(l>=r) printf("%lld
    ",(to1[Rank[r]]-to1[Rank[l]]+Mod)%Mod);
            else printf("0
    ");
        }
        return 0;
    }

     

  • 相关阅读:
    线性回归和 逻辑回归 的思考(参考斯坦福 吴恩达的课程)
    数据结构算法基础-内部排序算法
    机器学习《test》
    day1.接口测试(概念、Postman、SoapUI、jmeter)
    SQL2000 3核6核 CUP 安装SP4
    SQL常用语句
    SQL SERVER 2000数据库置疑处理
    常用终端命令
    c++ 位操作
    计算机为什么用补码存储数据?
  • 原文地址:https://www.cnblogs.com/Never-mind/p/10156409.html
Copyright © 2011-2022 走看看