求区间[l, r]中各个数的因数

求区间[l, r]中各个数的因数

今日通过一道题学会了一个使用调和级数(时间复杂度Ologn)求区间中各个数的因数,感觉还是数论的内容,记录一下。

题目概述:

给定l, r。求l-r中各个数的因数

代码:

void get_results(int l, int r) {
    std::vector<std::vector<int>> f(r + 1);
    for (int i = 1; i <= r; i ++) {
        for (int j = i; j <= r; j += i) {
            // 对于每个i,我们都从i开始往后以i为距离++,所以每个j都是当前i的倍数,i就是当前j的因子
            f[j].push_back(i);
        }
    }
    for (int i = l; i <= r; i ++) {
        std::cout << i << ":";
        for (int e : f[i]) {
            std::cout << e << " ";
        }
        std::cout << "\n";
    }
}

给出一道变形的题,加上状态压缩:

https://oj.cwnu.online-judge.cn/p/YS0005

题目概要:

给出n对数据,每一对数据为(string str, int x)的形式;并且给出一个字符串T。判断每一对字符串与x对应的目标串是否契合?契合yes;不契合no。

契合:x对应的目标串是指:x的所有因数对应的下标映射在字符串T的字符的集合STR。如果str中的所有字符都在STR中存在,那么就是契合

void solve() {
    int n;
    std::cin >> n;
    std::vector<std::pair<int, int>> a(n);
    for (int i = 0; i < n; i ++) {
        std::string str;
        std::cin >> str >> a[i].second; // 输入字符串和x
        for (auto e : str) {
            int t = e - 'a';
            a[i].first |= 1 << t;// 状态压缩,将字符串映射为int整数,每次将所有字符用位运算或,二进制中每一位对应一个小写字母,最后得到的二进制中位为1的就代表那一位对应的字母在str中存在
        }
    }
    std::string s;
    std::cin >> s;
    int len = s.size();
    std::vector<int> f(n+1);
    for (int i = 1; i <= len; i ++) {
        for (int j = i; j <= len; j += i) {
            // 调和级数,对于每一个i,往后遍历的每一个j都是i的倍数,所以i是j的一个因子。每次将i放入集合中,这道题是用与运算放入f集合的
            int t = s[i-1] - 'a';
            // i为j的因子,s[i-1]为映射到T中的字符,同样用状态压缩,将集合映射为int整数
            f[j] |= 1 << t;  // f[j]表示x对应字串的集合(去重)对应的二进制整数
        }
    }
    for (auto [x, y] : a) {
        // 位运算技巧,判断两个集合对应的状态压缩二进制的关系:
        // x 每一位属于 y :x | y == y
        std::cout << ((x | f[y]) == f[y] ? "YES" : "NO") << "\n"; 
    }
}
posted @ 2024-11-20 22:55  来杯whiskey  阅读(7)  评论(1编辑  收藏  举报