Gym - 101102J J. Divisible Numbers 位运算+优化+前缀和

来源:互联网 发布:mendeley for mac 编辑:程序博客网 时间:2024/06/05 18:22

J. Divisible Numbers
time limit per test
3.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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.

Output

Print the answer for each query on a single line.

Example
input
14 22 5 3 81 3 22 4 355
output
13



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

0 0
原创粉丝点击