1. 程式人生 > >BZOJ5285 & 洛谷4424 & UOJ384:[HNOI/AHOI2018]尋寶遊戲——題解

BZOJ5285 & 洛谷4424 & UOJ384:[HNOI/AHOI2018]尋寶遊戲——題解

排序 訪問 queue mes 完成 include clu 過程 printf

https://www.lydsy.com/JudgeOnline/problem.php?id=5285

https://www.luogu.org/problemnew/show/P4424

http://uoj.ac/problem/384

洛谷的題解已經很把思想過程完備地表達出來了:https://kelin.blog.luogu.org/solution-p4424

感覺比官方題解說的還清楚。

那麽問題就是我們到底應該如何實現這個算法呢?

一個直觀的想法是把每一位的數全部處理出來,然後排個序,之後根據給定的序列每位的0/1查找出答案應當在什麽區間內即可。

但是很玄妙的是我們排序要對原來的數進行排序,不能對其取模之後的答案排序。

於是這裏用了題解的寫法,排序用基數排序根據讀入直接完成。

#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int p=1e9+7;
const int M=5005;
int n,m,q,base
[M],w[M],a[M],b[M],c[M],t[M]; char s[M]; int main(){ scanf("%d%d%d",&n,&m,&q); base[1]=1; for(int i=2;i<=n+1;i++)base[i]=base[i-1]*2%p; for(int i=1;i<=m;i++)a[i]=i; for(int i=1;i<=n;i++){ scanf("%s",s+1);c[0]=0;c[1]=m; for(int j=1;j<=m;j++){
if(s[j]==1)w[j]=(w[j]+base[i])%p; else c[0]++; } for(int j=m;j>=1;j--){ b[c[s[a[j]]-0]--]=a[j]; } swap(a,b); } for(int i=1;i<=m;i++)t[i]=w[a[i]]; t[m+1]=base[n+1]; for(int i=1;i<=q;i++){ scanf("%s",s+1); int l=0,r=m+1; for(int j=m;j>=1;j--){ if(s[a[j]]==0){l=j;break;} } for(int j=1;j<=m;j++){ if(s[a[j]]==1){r=j;break;} } if(l>r)puts("0"); else printf("%d\n",(t[r]-t[l]+p)%p); } return 0; }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

BZOJ5285 & 洛谷4424 & UOJ384:[HNOI/AHOI2018]尋寶遊戲——題解