zoukankan      html  css  js  c++  java
  • loj #2494. 「AHOI / HNOI2018」寻宝游戏

    #2494. 「AHOI / HNOI2018」寻宝游戏

     

    题目描述

    某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会。

    作为新生的你对这个活动非常感兴趣。你每天都要从西向东经过教学楼一条很长的走廊,这条走廊是如此的长,以至于它被人戏称为 infinite corridor。一次,你经过这条走廊的时,注意到在走廊的墙壁上隐藏着 nnn 个等长的二进制的数字,长度均为 mmm。你从西向东将这些数字记录了下来,形成一个含有 nnn 个数的二进制数组 a1,a2,...,ana_1, a_2, ..., a_na1​​,a2​​,...,an​​。很快,在最新的一期 Voo Doo 杂志上,你发现了 qqq 个长度也为 mmm 的二进制串 r1,r2,...,rqr_1, r_2, ..., r_qr1​​,r2​​,...,rq​​。聪明的你很快发现了这些数字的含义。保持数组 a1,a2,...,ana_1, a_2, ..., a_na1​​,a2​​,...,an​​ 的元素顺序不变,你可以在它们之间插入 ∧wedge∧(按位与运算)或者 ∨vee∨(按位或运算)两种二进制运算符。例如:11011∧00111=00011,11011∨00111=1111111011 wedge 00111=00011,11011 vee 00111=111111101100111=00011,1101100111=11111。

    你需要插入恰好 nnn 个运算符,相邻两个数之间恰好一个,在第一个数的左边还有一个。如果我们在第一个运算符的左边补入一个 000,这就形成了一个运算式,我们可以计算它的值。与往常一样,运算顺序是从左往右。有趣的是,出题人已经告诉你这个值的可能的集合——Voo Doo 杂志里的那一些二进制数 r1,r2,...,rqr_1, r_2, ..., r_qr1​​,r2​​,...,rq​​,而解谜的方法,就是对 r1,r2,...,rqr_1, r_2, ..., r_qr1​​,r2​​,...,rq​​ 中的每一个值 rir_iri​​,分别计算出有多少种方法填入这 nnn 个运算符,使得这个运算式的值是 rir_iri​​ 。然而,infinite corridor 真的很长,这意味着数据范围可能非常大。因此,答案也可能非常大,但是你发现由于谜题的特殊性,你只需要求答案模 100000000710000000071000000007 (109+710^9 + 7109​​+7,一个质数)的值。

    输入格式

    第一行三个数 n,m,qn, m, qn,m,q,含义如题所述。

    接下来 nnn 行,其中第 iii 行有一个长度为 mmm 的二进制串,左边是最高位,表示 aia_iai​​ 。

    接下来 qqq 行,其中第 iii 行有一个长度为 mmm 的二进制串,左边是最高位,表示 rir_iri​​ 。

    输出格式

    输出 qqq 行,每行一个数,其中第 iii 行表示对应于 rir_iri​​ 的答案。

    样例

    样例输入 1

    5 5 1
    01110
    11011
    10000
    01010
    00100
    00100

    样例输出 1

    6

    样例输入 2

    10 10 3
    0100011011
    0110100101
    1100010100
    0111000110
    1100011110
    0001110100
    0001101110
    0110100001
    1110001010
    0010011101
    0110011111
    1101001010
    0010001001

    样例输出 2

    69
    0
    5

    数据范围与提示

    对于 10%10\%10% 的数据,n≤20,m≤30n le 20, m le 30n20,m30,q=1q = 1q=1

    对于另外 20%20\%20% 的数据,n≤1000n le 1000n1000,m≤16m le 16m16

    对于另外 40%40\%40% 的数据,n≤500n le 500n500,m≤1000m le 1000m1000

    对于 100%100\%100% 的数据,1≤n≤10001 le n le 10001n1000,1≤m≤50001 le m le 50001m5000,1≤q≤10001 le q le 10001q1000

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 50
    using namespace std;
    int n,m,q;
    bool a[maxn][maxn],b[maxn],c[maxn];
    bool check(int sta){
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(sta&(1<<i-1)) b[j]=(b[j]&a[i][j]);
                else b[j]=(b[j]|a[i][j]);
            }
        for(int i=1;i<=m;i++)if(b[i]!=c[i])return 0;
        return 1;
    }
    int main(){
        char s[maxn];
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
                a[i][j]=s[j]=='0'?0:1;
        }
        scanf("%s",s+1);
        for(int i=1;i<=m;i++)c[i]=s[i]=='0'?0:1;
        int ans=0;
        for(int sta=0;sta<(1<<n);sta++)
            if(check(sta))ans++;
        printf("%d",ans);
        return 0;
    }
    10分 暴力
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 5010
    #define mod 1000000007
    using namespace std;
    int n,m,q,rk[maxn],sum[maxn],tmp[maxn],pows[maxn];
    char s[maxn];
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=m;i++)rk[i]=i;
        pows[0]=1;
        for(int i=1;i<=n;i++)
            pows[i]=1LL*pows[i-1]*2%mod;
        for(int i=1;i<=n;i++){
            int cnt[]={0,0};
            scanf("%s",s+1);
            for(int j=1;j<=m;j++){
                sum[j]=(sum[j]+1LL*(s[j]-'0')*pows[i-1])%mod;
                cnt[s[j]-'0']++;
            }
            cnt[1]+=cnt[0];
            for(int j=m;j>=1;j--)
                tmp[cnt[s[rk[j]]-'0']--]=rk[j];
            swap(rk,tmp);
        }
        reverse(rk+1,rk+m+1);
        for(int i=1;i<=q;i++){
            scanf("%s",s+1);
            int lst1=0,fst0=m+1;
            for(int j=m;j>=1&&lst1==0;j--)
                if(s[rk[j]]-'0')lst1=j;
            for(int j=1;j<=m&&fst0==m+1;j++)
                if(!(s[rk[j]]-'0'))fst0=j;
            if(lst1>fst0){puts("0");continue;}
            int c0=lst1>=1?sum[rk[lst1]]:pows[n];
            int c1=fst0<=m?sum[rk[fst0]]:0;
            printf("%d
    ",(c0-c1+mod)%mod);
        }
        return 0;
    }
    100分
  • 相关阅读:
    APP测试之找密码
    测试理论
    LR性能测试
    Linux 操作系统常用命令
    C#后台HttpWebRequest代码调用WebService
    Python3在Windows下安装虚拟环境
    oracle使用rownum进行分页查询
    oracle over结合row_number分区进行数据去重处理
    Oracle实现主键自动增长
    Asp.net WebApi调用
  • 原文地址:https://www.cnblogs.com/thmyl/p/8928397.html
Copyright © 2011-2022 走看看