zoukankan      html  css  js  c++  java
  • [HNOI/AHOI2018]寻宝游戏

    题目大意:
      $n(nle1000)$个$m(mle5000)$位的二进制数,第$0$个数为$0$。用$wedge$和$vee$将这些数连接起来。$q(qle1000)$次询问,每次给定一个$m$位二进制数$r$,问有多少种连接方案使得结果为$r$。

    思路:
      参考myy的官方题解:

    如果第$i$个数之前的运算符是$wedge$,则这一位设为$1$,否则为$0$,得到的二进制数记为$x$。

    对每一位分别考虑,对于第$i$位,如果第$j$个数是$1$,那么这一位设为$1$,否则为$0$,得到的二进制数记为$b_i$。

    以左边为最低位,按前缀归纳容易证明,第$i$位的结果为$1$,当且仅当$x<b_i$。

    我们将$b$从大到小排序,结果设为$c$,那么答案不为零仅当在$c$的顺序下,$r$中没有任何$0$在$1$的前面。找到$r$中第一个$0$的位置,假设是$k$,那么解$x$要满足$c_kle x<c_{k-1}$,于是答案是$c_{k-1}-c_k$。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<climits>
     4 #include<algorithm>
     5 #include<sys/mman.h>
     6 #include<sys/stat.h>
     7 typedef long long int64;
     8 class MMapInput {
     9     private:
    10         char *buf,*p;
    11         int size;
    12     public:
    13         MMapInput() {
    14             register int fd=fileno(stdin);
    15             struct stat sb;
    16             fstat(fd,&sb);
    17             size=sb.st_size;
    18             buf=reinterpret_cast<char*>(mmap(0,size,PROT_READ,MAP_PRIVATE,fileno(stdin),0));
    19             p=buf;
    20         }
    21         char getchar() {
    22             return (p==buf+size||*p==EOF)?EOF:*p++;
    23     }
    24 };
    25 MMapInput mmi;
    26 inline int getint() {
    27     register char ch;
    28     while(!isdigit(ch=mmi.getchar()));
    29     register int x=ch^'0';
    30     while(isdigit(ch=mmi.getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    31     return x;
    32 }
    33 inline int getdigit() {
    34     register char ch;
    35     while(!isdigit(ch=mmi.getchar()));
    36     return ch^'0';
    37 }
    38 const int N=1001,M=5000,mod=1e9+7;
    39 int pow[M],rank[M],tmp[M],a[M],sum[M];
    40 int main() {
    41     const int n=getint(),m=getint(),q=getint();
    42     for(register int i=0;i<m;i++) rank[i]=i;
    43     for(register int i=pow[0]=1;i<=n;i++) {
    44         pow[i]=pow[i-1]*2%mod;
    45     }
    46     for(register int i=0;i<n;i++) {
    47         int cnt[2]={-1,m-1};
    48         for(register int j=0;j<m;j++) {
    49             if(!(a[j]=getdigit())) cnt[0]++;
    50             sum[j]=(sum[j]+(int64)a[j]*pow[i])%mod;
    51         }
    52         for(register int j=m-1;~j;j--) {
    53             tmp[cnt[a[rank[j]]]--]=rank[j];
    54         }
    55         std::swap(rank,tmp);
    56     }
    57     std::reverse(&rank[0],&rank[m]);
    58     for(register int i=0;i<q;i++) {
    59         for(register int i=0;i<m;i++) a[i]=getdigit();
    60         int last1=INT_MIN,first0=INT_MAX;
    61         for(register int i=m-1;~i;i--) {
    62             if(a[rank[i]]) {
    63                 last1=i;
    64                 break;
    65             }
    66         }
    67         for(register int i=0;i<m;i++) {
    68             if(!a[rank[i]]) {
    69                 first0=i;
    70                 break;
    71             }
    72         }
    73         if(last1>first0) {
    74             puts("0");
    75             continue;
    76         }
    77         const int sum1=last1==INT_MIN?pow[n]:sum[rank[last1]];
    78         const int sum2=first0==INT_MAX?0:sum[rank[first0]];
    79         printf("%d
    ",(sum1-sum2+mod)%mod);
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    Python之print字典
    SpringBoot入门 (六) 数据库访问之Mybatis
    SpringBoot入门 (四) 数据库访问之JdbcTemplate
    SpringBoot入门 (三) 日志配置
    SpringBoot入门 (一) HelloWorld
    设计模式之装饰器模式
    设计模式之模板模式
    spring之mvc原理分析及简单模拟实现
    设计模式之单例
    国产密码研究
  • 原文地址:https://www.cnblogs.com/skylee03/p/8858304.html
Copyright © 2011-2022 走看看