求区间[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; // 输入字符串和xfor (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 == ystd::cout << ((x | f[y]) == f[y] ? "YES" : "NO") << "\n"; }
}