[HNOI/AHOI2018] Scavenger Hunt

The main idea of ​​the title:
  $n(n\le1000)$ $m(m\le5000)$ binary numbers, the $0$ number is $0$. Concatenate the numbers with $\wedge$ and $\vee$. Ask $q(q\le1000)$ times, each time a binary number $r$ of $m$ bits is given, and ask how many connection schemes make the result $r$.

Ideas:
  Refer to myy's official solution:

If the operator before the $i$ number is $\wedge$, this bit is set to $1$, otherwise it is $0$, and the resulting binary number is recorded as $x$.

Considering each bit separately, for the $i$ bit, if the $j$ number is $1$, then this bit is set to $1$, otherwise it is $0$, and the resulting binary number is recorded as $b_i$.

Taking the left as the lowest bit, it is easy to prove by prefix induction that the result of the $i$ bit is $1$ if and only if $x<b_i$.

We sort $b$ from large to small, and the result is set to $c$, then the answer is not zero only if in the order of $c$, there is no $0$ in $r$ before $1$. Find the position of the first $0$ in $r$, assuming it is $k$, then the solution of $x$ must satisfy $c_k\le x<c_{k-1}$, so the answer is $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\n",(sum1-sum2+mod)%mod);
80     }
81     return 0;
82 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324518346&siteId=291194637