逆推 Gym 101102J

题目链接:http://codeforces.com/gym/101102/problem/J

题目大意可以看这个人的:http://www.cnblogs.com/chen9510/p/5933624.html

思路:因为第一位是没有什么用的,因为任意的数都能被1整除,所以我们的范围就变到了0~512。

所以我们预处理处sum(i,j)。其中sum(i,j)表示目前是第i个a[i],能被j整除的个数。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha
")
const int maxn = 1e5 + 5;
int sum[maxn][550];
int n, q;
int a[maxn];

int main(){
    int t; cin >> t;
    while (t--){
        scanf("%d%d", &n, &q);
        for (int i = 1; i <= n; i++)
            for (int j = 0; j <= 512; j++)
                sum[i][j] = 0;
        for (int i = 1; i <= n; i++){
            scanf("%d", a + i);
            int bit = 0;
            for (int j = 2; j <= 10; j++){///不要第一位了
                if (a[i] % j == 0) bit += (1 << (j - 2));
            }
            for (int j = 0; j <= 512; j++){///因为不要第一位了,所以是512
                sum[i][j] = sum[i - 1][j] + ((j & bit) ? 1 : 0);
            }
        }
        while (q--){
            int l, r, val;
            scanf("%d%d%d", &l, &r, &val);
            if (val % 2) {
                printf("%d
", r - l + 1);
                continue;
            }
            printf("%d
", sum[r][val >> 1] - sum[l - 1][val >> 1]);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/heimao5027/p/6736102.html