概述
You are given an array A of integers of size N, and Q queries. For each query, you will be given a set of distinct integers S and two integers L and R that represent a range in the array. Your task is to count how many numbers in the given range are divisible by at least one number from the set.
The first line of input contains a single integer T, the number of test cases.
The first line of each test case contains two integers, N and Q (1 ≤ N, Q ≤ 105), the size of the array and the number of queries, respectively.
The next line contains N space-separated integers, the values of the array A (1 ≤ Ai ≤ 109).
Each of the next Q lines contain the description of one query in the form:
LRS
Where L and R (1 ≤ L ≤ R ≤ N) represent the range, and S is an integer between 1 and 1023 (inclusive) and represents the set; consider the binary representation of the number S, if the ith bit (1-based) is 1, then the number i belongs to the set. Since S is less than1024, the values in the set are between 1 and 10.
For example: if S is equal to 6, the binary representation of 6 is 110, and this means the values in the set are 2 and 3.
The input was given in this way to reduce the size of the input file.
Print the answer for each query on a single line.
1 4 2 2 5 3 8 1 3 2 2 4 355
1 3
Source
2016 ACM Amman Collegiate Programming Contest
UESTC 2017 Winter Training #1
Gym - 101102J
My Solution
题意:给出n个数,然后每次询问l r s,表示在lr区间内有多少个x,是x能被集合s里的至少一个元素整除,s表示一个{1~10}的子集
位运算+优化+前缀和
可以预处理出前缀和 sum[i][j]表示1~j中能被集合i满足的数的个数,
且i为奇数时比有元素1,lr区间内所有的数必定可以被1整除,所以只剩下512中情况
故 int sum[512][maxn];
读入的时候每次判断v可以被哪些数整除,然后得到集合s,s说表示的集合中所有的元素皆可以整除v,
然后用这个s和0~512位于返回非0值则有公共元素,则sum[j][i] = sum[j][i-1] + 1,否则只是普通传递 sum[j][i] = sum[j][i-1];
对于l r s
当s为偶数时 ans = sum[s>>1][r] - sum[s>>][l-1]; s为奇数时 ans = r - l + 1;
复杂度 O(n*512)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 8;
template <class T>
inline void cinn(T &ret)
{
char c = getchar();
while(c < '0' || c > '9')
c = getchar();
ret = c - '0';
while(c = getchar(), c>='0' && c<='9')
ret = ret * 10 + (c - '0');
}
inline void coutt(int a)
{ // 输出外挂
if (a < 0)
{
putchar('-');
a = -a;
}
if (a >= 10)
{
coutt(a / 10);
}
putchar(a % 10 + '0');
}
int sum[512][maxn];
int main()
{
#ifdef LOCAL
freopen("g.txt", "r", stdin);
//freopen("g.coutt", "w", stdcoutt);
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
int T, n, q, v, i, j, l, r, s;
cinn(T);
while(T--){
cinn(n); cinn(q);
for(i = 1; i <= n; i++){
cinn(v);
s = 0;
for(j = 2; j <= 10; j++){
if(v % j == 0) s |= 1<<(j - 2);
}
//ccoutt << s << endl;
for(j = 0; j < 512; j++){
sum[j][i] = sum[j][i - 1];
if(j & s) sum[j][i] += 1;
}
}
while(q--){
cinn(l); cinn(r); cinn(s);
if(s&1) coutt(r - l + 1);
else coutt(sum[s>>1][r] - sum[s>>1][l - 1]);
puts("");
}
}
return 0;
}
Thank you!
------from ProLights
最后
以上就是甜甜含羞草为你收集整理的Gym - 101102J J. Divisible Numbers 位运算+优化+前缀和的全部内容,希望文章能够帮你解决Gym - 101102J J. Divisible Numbers 位运算+优化+前缀和所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复