携程2025.8.26秋招笔试题解
携程2025.8.26秋招笔试题解
t1
签到题,手动模拟
python代码
import sys
def main():
    n = int(input().strip())
    cur = 0
    num = 0
    while True:
        s = str(num)
        if cur + len(s) >= n:
            print(s[n - cur - 1])
            break
        else:
            cur += len(s)
            num += 2
if __name__ == "__main__":
    main()
cpp代码
#include <iostream>
#include <string>
int n;
int main() {
    std::cin >> n;
    int cur = 0, num = 0;
    std::string s;
    while (true) {
        s = std::to_string(num);
        if (cur + s.length() >= n) {
            std::cout << s[n - cur - 1];
            break;
        }
        else {
            cur += s.length();
            num += 2;
        }
    }
    return 0;
}
t2
既然和公约数有关,那么我们首先会想到分解质因数,想到分解质因数就会想到筛质数。
思路就是:
- 筛质数
- 根据筛选出的质数去求最大长度
- 筛选满足最大长度的质数,并且利用gcd去重
 注意最后筛选的candidates来自于cover而不是primes,因为primes里面只有\(sqrt(n)\)以下的质数,而cover经过更新以后,可以包含全量的满足条件的质数(即包括了大于\(sqrt(n)\)的部分)
python代码
import sys, math
def select_primes(upper, flags, primes: list):
    for i in range(2, upper):
        if not flags[i]:
            primes.append(i)
        for pj in primes:
            if pj > upper // i:
                break
            flags[pj * i] = True
            if i % pj == 0:
                break
def resolve(x, primes):
    res = []
    for pi in primes:
        if x % pi == 0:
            res.append(pi)
            while x % pi == 0:
                x //= pi
    # 记得不要漏掉x本身是质数的情况
    if x > 1:
        res.append(x)
    return res
def read_int():
    with open('input.txt', 'r', encoding='utf-8') as file:
        data = file.read().strip().split()
        for i in data:
            yield int(i)
def main():
    it = iter(read_int())
    n = next(it, 0)
    print(n)
    
    freqs = {}
    _max = 0
    # 没必要获取全部的输入,只要拿到>1的那部分就行了
    for _ in range(n):
        num = next(it)
        if num <= 1:
            continue
        freqs[num] = freqs.get(num, 0) + 1
        _max = max(_max, num)
    if len(freqs.keys()) == 0:
        print("0 0")
        sys.exit(0)
    # 筛质数
    upper = math.isqrt(_max) + 1
    prime_flag = [False] * (upper + 1)
    primes: list[int] = []
    select_primes(upper, prime_flag, primes)
    # 分解质因数,求最大长度
    cover = {} # 每个质数能覆盖几个元素
    base = {} # 每个质数覆盖的元素组当中,各个元素的gcd是多少
    for n, t in freqs.items():
        for pi in resolve(n, primes):
            cover[pi] = cover.get(pi, 0) + t
            base[pi] = n if pi not in base else math.gcd(base[pi], n)
    ans = max(cover.values(), default=1)
    if ans == 1:
        print(f"1 {len(freqs)}")
        sys.exit(0)
    # 统计答案
    seen = set()
    cnt = 0
    candidates = [pi for pi in cover if cover[pi] == ans]
    for pi in candidates:
        if pi in seen:
            continue
        for qi in resolve(base[pi], primes):
            seen.add(qi)
        cnt += 1
    
    print(f"{ans} {cnt}")
if __name__ == "__main__":
    main()
cpp代码
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <unordered_map>
#include <unordered_set>
constexpr int N = 2e6 + 5, M = 2e8 + 5;
int P = static_cast<int>(std::sqrt(M));
std::unordered_map<int, int> freqs, cover, base;
std::vector<int> primes, factors;
int n;
inline void select_primes(int upper) {
    std::vector<char> flag (upper + 1, 0);
    for (int i = 2; i <= upper; i++) {
        if (!flag[i])
            primes.emplace_back(i);
        for (int j = 0; j < primes.size() && primes[j] <= upper / i; j++) {
            flag[primes[j] * i] = true;
            if (i % primes[j] == 0)
                break;
        }
    }
}
void resolve(int x) {
    factors.clear();
    for (auto pi: primes) {
        if (x % pi == 0) {
            factors.push_back(pi);
            while (x % pi == 0) {
                x /= pi;
            }
        }
    }
    if (x != 1) {
        factors.push_back(x);
    }
}
int gcd(int x, int y) {
    if (!y) {
        return x;
    }
    return gcd(y, x%y);
}
int main() {
    std::freopen("input.txt", "r", stdin);
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    // 没必要获取全部输入,只要>1的
    int x, _max = 0;
    std::cin >> n;
    for (int i = 1; i <= n; i++) {
        std::cin >> x;
        if (x <= 1)
            continue;
        freqs[x]++;
        _max = std::max(_max, x);
    }
    if(freqs.empty()) {
        std::cout << "0 0";
        return 0;
    }
    int upper = static_cast<int>(std::sqrt(_max)) + 1;
    // 筛质数
    select_primes(upper);
    // 统计长度
    int L = 0;
    for (auto &pi: freqs) {
        int key = pi.first;
        resolve(key);
        for (auto ai: factors) {
            cover[ai] += pi.second;
            if (base.find(ai) == base.end()) {
                base[ai] = pi.first;
            } else {
                base[ai] = gcd(base[ai], pi.first);
            }
        }
    }
    for (auto &pi: cover) {
        L = std::max(L, pi.second);
    }
    if (L == 1) {
        std::cout << L << " " << freqs.size() << std::endl;
        return 0;
    }
    std::unordered_set<int> seen;
    int ans = 0;
    // 注意这里是cover而不是primes
    for (auto &pi: cover) {
        if (seen.contains(pi.first)) 
            continue;
        if (cover[pi.first] < L) {
            continue;
        }
        resolve(base[pi.first]);
        for (auto &vi: factors) {
            seen.insert(vi);
        }
        ans++;
    }
    std::cout << L << " " << ans << std::endl;
    return 0;
}
t3
这道题介于POJ 2352 Stars和HH的项链之间
python code
# 其实r没有必要做离散化,浪费了性能
# 我们只需要压缩l的值域即可.
# 这个版本的离散化写得有问题,应该输入全部读完以后统一离散化,否则两个部分的输入值域不同,离散化结果也是错误的
import sys
import bisect
input = sys.stdin.readline
N = int(5e5 + 5)
M = int(1e9 + 5)
class TreeArr:
    def __init__(self, len):
        self.len = len
        self.arr = [0] * (len + 1)
    
    def update(self, pos, x):
        while (pos <= self.len):
            self.arr[pos] += x
            pos += (pos & (-pos))
    
    def query(self, pos):
        res = 0
        while pos:
            res += self.arr[pos]
            pos -= (pos & (-pos))
        return res
def main():
    n, m = tuple(map(int, input().strip().split()))
    origin_vals = []
    bacs: list[tuple] = []
    for _ in range(n):
        l, r = tuple(map(int, input().strip().split()))
        origin_vals.append(l)
        origin_vals.append(r)
        bacs.append((l, r))
    # 离散化
    vals = sorted(set(origin_vals))
    _max = len(vals)
    func = lambda x: bisect.bisect_left(vals, x) + 1
    for i in range(len(bacs)):
        bacs[i] = (func(bacs[i][0]), func(bacs[i][1]))
    bacs = sorted(bacs, key=lambda x: x[1])
    
    origin_vals.clear()
    # 记录查询
    queries = []
    for i in range(m):
        l, r = tuple(map(int, input().strip().split()))
        queries.append((i, l, r))
        origin_vals.append(l)
        origin_vals.append(r)
    
    # 离散化
    for i in range(len(queries)):
        queries[i] = (queries[i][0], func(queries[i][1]), func(queries[i][2]))
    queries = sorted(queries, key=lambda x: x[2])
    tree_arr =TreeArr(_max)
    idx = 0
    ans = [0] * m
    # 计算答案
    for i in range(m):
        qid, ql, qr = queries[i]
        while idx < len(bacs) and bacs[idx][1] <= qr:
            tree_arr.update(bacs[idx][0], 1)
            idx += 1
        ans[qid] = idx - tree_arr.query(ql - 1)
    
    print("\n".join(map(str, ans)))
if __name__ == "__main__":
    main()
cpp code
因为使用了vector,下标能从零开始就尽量从零开始吧。
// POJ 2352 Stars
#include <algorithm>
#include <array>
#include <cstdio>
#include <iterator>
#include <random>
#include <vector>
constexpr int N = 1e5 + 5, M = 1e9 + 5;
using PII = std::pair<int, int>;
std::vector<int> origin_vals;
std::vector<PII> bacs;
std::vector<std::tuple<int, int, int>> queries;
int n, m;
inline int lowbit(int x) {
    return x & (-x);
}
struct TreeArr {
    int len;
    std::vector<int> arr;
    TreeArr(int l): len(l) {
        arr.resize(len + 1, 0);
    }
    void update(int pos, int x) {
        while (pos <= len) {
            arr[pos] += x;
            pos += lowbit(pos);
        }
    }
    int query(int pos) {
        int res = 0;
        while (pos) {
            res += arr[pos];
            pos -= lowbit(pos);
        }
        return res;
    }
};
inline int mapping(std::vector<int> &a, int x) {
    return (std::lower_bound(a.begin(), a.end(), x) - a.begin()) + 1;
}
int main() {
    std::freopen("input.txt", "r", stdin);
    scanf("%d%d", &n, &m);
    int l, r;
    bacs.resize(n);
    queries.resize(m);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &l, &r);
        origin_vals.push_back(l);
        bacs[i] = {l, r};
    }
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &l ,&r);
        origin_vals.push_back(l);
        queries[i] = std::tuple{r, l, i};
    }
    // 离散化
    std::sort(origin_vals.begin(), origin_vals.end());
    origin_vals.erase(std::unique(origin_vals.begin(), origin_vals.end()), origin_vals.end());
    for (int i = 0; i < n; i++) {
        bacs[i].first = mapping(origin_vals, bacs[i].first);
    }
    for (int i = 0; i < m; i++) {
        std::get<1>(queries[i]) = mapping(origin_vals, std::get<1>(queries[i]));
    }
    auto func = [](PII a, PII b)->bool {return a.second < b.second;};
    std::sort(bacs.begin(), bacs.end(), func);
    std::sort(queries.begin(), queries.end());
    auto tree_arr = TreeArr(origin_vals.size());
    int idx = 0;
    std::vector<int> ans(m, 0);
    for (int i = 0; i < m; i++) {
        while (idx < n && bacs[idx].second <= std::get<0>(queries[i])) {
            tree_arr.update(bacs[idx].first, 1);
            idx++;
        }
        int t = std::get<2>(queries[i]);
        ans[t] = idx - tree_arr.query(std::get<1>(queries[i]) - 1);
    }
    for (int i = 0; i < m; i++) 
        printf("%d\n", ans[i]);
    return 0;
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号