求区间[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";
}
}
标签:std,各个,int,因数,vector,str,区间,契合
From: https://www.cnblogs.com/zj-cnbolgs/p/18559550