搜狗2020校招【后端】笔试(第二场)

两道编程题的题解

密码生成

链接:https://www.nowcoder.com/questionTerminal/96bf0c548a094de7a05919e0b32b1a5a
来源:牛客网
 

小汪作为一个有数学天分的程序猿,设计了一套密码生成器来搞定自己的密码问题。
密码生成器由N个槽位组成,槽位的下标为0~N-1,每个槽位存储一个数。起初每个槽位都是0。
密码生成器会进行M轮计算,每轮计算,小汪会输入两个数L,R(L<=R),密码生成器会将这两个数作为下标,将两个下标之间(包含)的所有槽位赋值为i(i为当前的轮次,i∈[1,M])。
M轮计算完成后,密码生成器会根据槽位的最终值生成一条密码,密码的生成规则为:
(0*a[0] + 1*a[1] + 2*a[2] + ... + (N-1)*a[N-1]) mod 100000009
其中a[i]表示第i个槽位的最终值。
请帮助小汪把他的密码生成器实现为代码。

 

输入描述:

第一行为两个整数N,M,表示槽位个数和计算轮数。
接下来M行,每行两个整数Li,Ri,表示第i轮计算的输入。


 

输出描述:

输出一行,一个整数A,表示小汪的开机密码。

示例1

输入

5 3
2 3
1 2
1 1

输出

10

题解:排序+优先队列

#include <bits/stdc++.h>

using namespace std;

const int N = (int)2e5 + 5;
const int MOD = 100000009;

struct Segment {
  int l, r, timer;
  Segment() {}
  Segment(int _l, int _r, int _timer) : l(_l), r(_r), timer(_timer) {}
  bool operator< (const Segment& x) const {
    return timer < x.timer;
  }
}f[N];
int s[N];

priority_queue<Segment> que;

int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 0; i < m; i++) {
    int l, r;
    scanf("%d %d", &l, &r);
    f[i] = Segment(l, r, i + 1);
  }
  f[m] = Segment(0, n - 1, 0);
  m++;
  sort(f, f + m, [&](Segment x, Segment y) {
    if (x.l == y.l) {
      return x.r > y.r;
    }
    return x.l < y.l;
  });
  int cur = 0;
  for (int i = 0; i < n; i++) {
    while (cur < m && f[cur].l == i) {
      que.push(f[cur]);
      cur++;
    }
    while (que.top().r < i) que.pop();
    s[i] = que.top().timer;
  }
  int ans = 0;
  for (int i = 0; i < n; i++) {
    ans = (ans + (i * 1LL * s[i]) % MOD) % MOD;
  }
  cout << ans << endl;
  return 0;
}

IP过滤器

 

链接:https://www.nowcoder.com/questionTerminal/8389e1ccd47d40ba859c2497a428d0ca
来源:牛客网
 

在搜索引擎后端服务中,需要对恶意的抓取进行限制,其中的一个环节即对访问IP进行限制。请设计一个IP过滤器,实现对访问的IP限制的功能。对IP的限制数据有三种格式:
1.全IP:如222.205.58.16
2.前面带 *:如 *.58.16
3.后面带 *:如 222.205.58.*
带 * 的表示匹配到任意的IP段均可,且 * 可以代表多个ip段,且 * 只能出现在开头或者结尾。
现给出若干条需要过滤的规则,以及若干输入的IP,你需要输出这若干条IP是否会被过滤

 

输入描述:

输入的第一行是过滤规则的条数N和需要过滤的IP数量M,之后的N行为IP的过滤规则且均合法,再之后的M行为需要进行判断是否被过滤的IP。其中N<100,M<50。


 

输出描述:

0:该条IP不会被过滤
1:该条IP会被过滤
总共M条需要判断的IP需要以空格作为区分

示例1

输入

5 3
222.205.58.16
*.58.16
222.205.58.*
*.16
224.*
222.205.58.17
222.205.59.19
223.205.59.16

输出

1 0 1

 

题解:暴力匹配即可

#include <bits/stdc++.h>

using namespace std;

int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  vector<string> foo, bar;
  for (int i = 0; i < n; i++) {
    string ss;
    cin >> ss;
    if (ss[0] == '*' || ss.back() == '*') {
      foo.push_back(ss);
    } else {
      bar.push_back(ss);
    }
  }
  auto ok = [&](string s1, string s2) -> bool {
    if (s1[0] == '*') {
      reverse(s1.begin(), s1.end());
      reverse(s2.begin(), s2.end());
    }
    int i = 0, j = 0;
    while (i < (int)s1.size() && j < (int)s2.size()) {
      if (s1[i] == '*') {
        return true;
      }
      if (s1[i] != s2[j]) {
        return false;
      }
      i++;
      j++;
    }
    return false;
  };
  auto check1 = [&](string ss) -> bool {
    for (string b : bar) {
      if (ss == b) {
        return true;
      }
    }
    return false;
  };
  auto check2 = [&](string ss) -> bool {
    for (string f : foo) {
      if (ok(f, ss)) {
        return true;
      }
    }
    return false;
  };
  for (int i = 0; i < m; i++) {
    string ss;
    cin >> ss;
    if (check1(ss) || check2(ss)) {
      cout << "1" << " ";
    } else {
      cout << "0" << " ";
    }
  }
  cout << endl;
  return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值