uoj384 HNOI2018 寻宝游戏

http://uoj.ac/problem/384

这道题有点厉害..

考虑 \(or\) \(and\) 运算的性质

如果在某一个位置\(and\)上\(0\) 或者 \(or\)上\(1\)

是不是前面的操作都白费了

于是按位考虑 压缩一下状态 以最右边的数作为最高位

设对于位\(i\)的状态是\(b_i\)

操作的序列同样压缩成\(op\)

\(or\) 是 \(0\) \(and\) 是 \(1\) (其实只需要建立一个\(and, or\) 和\(bit0, bit1\)的偏序关系就好了)

如果对于\(ans_i = 1\) 那么有\(b_i > op\)

同理对于\(ans_i = 0\) 那么有\(b_i \le op\)

统计答案的时候就是解若干个关于op的方程组

合并成\(l \le op < r\)的形式 那么\(result = r - l\)

解方程组的话可以先对\(\{b\}\)排序考虑第一次出现\(0,1\)位置

复杂度\(O((q + n) \times m)\)

#include <bits/stdc++.h>
#define int long long
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
  using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
  x = 0;char c = getchar(); bool f = 0;
  for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
  for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
  if(f) x = -x;
}
template<typename tp> inline void arr(tp *a, int n) {
  for(int i = 1; i <= n; i ++)
    cout << a[i] << " ";
  puts("");
}
const int M = 5555;
const int mo = 1e9 + 7;
template<typename tp> inline int sub(tp a, tp b) {
  int ans = a - b; for(; ans < 0; ans += mo); return ans;
}
struct Node {
  vector<int> vec;
  int ha, id;
}a[M];
int n, m, q;
int r[M], rnk[M], pw[M];
char str[M];
inline bool cmp(const Node &a, const Node &b) {
  for(int k = n - 1; k >= 0; k --)
    if(a.vec[k] != b.vec[k])
      return a.vec[k] < b.vec[k];
  return a.id < b.id;
}
main(void) {
  read(n); read(m); read(q);
  pw[0] = 1;
  for(int i = 1; i <= n; i ++)
    pw[i] = pw[i - 1] * 2 % mo;
  for(int i = 1; i <= n; i ++) {
    scanf("%s", str + 1);
    for(int k = 1; k <= m; k ++)
      a[k].vec.push_back(str[k] - '0');
  }
  for(int i = 1; i <= m; i ++) {
    int ha = 0;
    for(int k = n - 1; k >= 0; k --)
      ha = (ha * 2 + a[i].vec[k]) % mo;
    a[i].ha = ha; a[i].id = i;
  }
  sort(a + 1, a + m + 1, cmp); reverse(a + 1, a + m + 1);
  for(int k = 1; k <= m; k ++) rnk[a[k].id] = k;
  for(int i = 1; i <= q; i ++) {
    scanf("%s", str + 1);
    for(int k = 1; k <= m; k ++)
      r[rnk[k]] = str[k] - '0';
    int last1 = -1, first0 = m + 1;
    for(int k = 1; k <= m; k ++)
      if(r[k] == 0) {
        first0 = k;
        break;
      }
    for(int k = m; k >= 1; k --)
      if(r[k] == 1) {
        last1 = k;
        break;
      }
    if(first0 < last1) puts("0");
    else {
      if(last1 == -1) cout << sub(pw[n], a[first0].ha) << "\n";
      else cout << sub(a[last1].ha, a[last1 + 1].ha) << "\n";
    }
  }
}

原文地址:https://www.cnblogs.com/foreverpiano/p/8987475.html

时间: 2024-10-11 18:42:51

uoj384 HNOI2018 寻宝游戏的相关文章

bzoj千题计划310:bzoj5285: [Hnoi2018]寻宝游戏(思维题+哈希)

https://www.lydsy.com/JudgeOnline/problem.php?id=5285 |0 和 &1 没有影响 若填‘|’,记为0,若填‘&’,记为1 先只考虑最后一位 若要求最后=1 那么最后一个|1 要在最后一个 &0 后面 将n个数的最后一位拿出来构成一个01序列 填在所有数最后一位之前的运算符也拿出来构成一个01序列 将第n个数所在位置视为最高位 对于最高位来说 如果数字序列 和 运算符序列 都是0或都是1,没有影响 如果数字序列是0,运算符序列是1,

寻宝游戏(bzoj 3991)

Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止.小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程.但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小

bzoj 3991: [SDOI2015]寻宝游戏

Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止.小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程.但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小

【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set

[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止.小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程.但是这个游戏中宝物经常变化,有时某个村庄中会突

[SDOI2015][BZOJ3991] 寻宝游戏|set|dfs序|虚树|树上倍增LCA

3991: [SDOI2015]寻宝游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 427  Solved: 212[Submit][Status][Discuss] Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直

【BZOJ】【3991】【SDOI2015】寻宝游戏

dfs序 我哭啊……这题在考试的时候(我不是山东的,CH大法吼)没想出来……只写了50分的暴力QAQ 而且苦逼的写的比正解还长……我骗点分容易吗QAQ 骗分做法: 1.$n,m\leq 1000$: 直接找一个关键点做根进行深搜,算出其他关键点都与root连通的最小边权和,再×2 2.一条链的情况:用set维护序列中哪些点选了,然后ans=(sum[tail]-sum[head])*2; 其中sum[i]表示从序列首到第 i 个的边长之和……嗯就是前缀和优化一下= =取首和尾这一段的Len之和

刷题总结——寻宝游戏(bzoj3991 dfs序)

题目: Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止.小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程.但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失

【BZOJ 3991】 [SDOI2015]寻宝游戏

3991: [SDOI2015]寻宝游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 251 Solved: 137 [Submit][Status][Discuss] Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直

[洛谷P4424][HNOI/AHOI2018]寻宝游戏(bitset)

P4424 [HNOI/AHOI2018]寻宝游戏 某大学每年都会有一次Mystery Hunt的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为新生的你,对这个活动非常感兴趣.你每天都要从西向东经过教学楼一条很长的走廊,这条走廊是如此的长,以至于它被人戏称为infinite corridor.一次,你经过这条走廊时注意到在走廊的墙壁上隐藏着nn 个等长的二进制的数字,长度均为mm .你从西向东将这些数字记录了下来,形成一个含有nn 个数的二进制