口算训练(唯一分解定理 + 二分+2018年女生赛)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6287

题目:

口算训练

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 177    Accepted Submission(s): 41


Problem Description
小Q非常喜欢数学,但是他的口算能力非常弱。因此他找到了小T,给了小T一个长度为n 的正整数序列a1,a2,...,an ,要求小T抛出m 个问题以训练他的口算能力。

每个问题给出三个正整数
l,r,d ,小Q需要通过口算快速判断al×al+1×...×ar1×ar 是不是d 的倍数。

小Q迅速地回答了出来,但是小T并不知道正确答案是什么,请写一个程序帮助小T计算这些问题的正确答案。
 
Input
第一行包含一个正整数T(1T10) ,表示测试数据的组数。

每组数据第一行包含两个正整数
n,m(1n,m100000) ,分别表示序列长度以及问题个数。

第二行包含
n 个正整数a1,a2,...,an(1ai100000) ,表示序列中的每个数。

接下来
m 行,每行三个正整数l,r,d(1lrn,1d100000) ,表示每个问题。
 
Output
对于每个问题输出一行,若是倍数,输出Yes,否则输出No。
 
Sample Input
1
5 4
6 4 7 2 5
1 2 24
1 3 18
2 5 17
3 5 35
 
Sample Output
Yes
No
No
Yes
 
思路:如博客题目所言,唯一分解定理+二分。首先将所有的a进行素数分解,然后用一个vector记录这个素数出现的位置(如x % i == 0, 此时x 是第8位数,那么p[i].push_back(8)),然后二分从d分解出来的素数在该区间内出现总次数是否大于它在d中的次数。
代码实现如下:
 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int maxn = 1e5 + 7;
 7 int t, n, m, l, r, d, x;
 8 
 9 vector<int> G[maxn];
10 
11 int check(int l, int r, int x) {
12     return upper_bound(G[x].begin(), G[x].end(), r) - lower_bound(G[x].begin(), G[x].end(), l);
13 }
14 
15 bool slove(int l, int r, int x) {
16     for(int i = 2; i * i <= x; i++) {
17         int cnt = 0;
18         if(x % i == 0) {
19             while(x % i == 0) {
20                 cnt++;
21                 x /= i;
22             }
23             if(cnt > check(l, r, i)) {
24                 return false;
25             }
26         }
27     }
28     if(x > 1) {
29         if(check(l, r, x) < 1) {
30             return false;
31         }
32     }
33     return true;
34 }
35 
36 int main() {
37     scanf("%d", &t);
38     while(t--) {
39         scanf("%d%d", &n, &m);
40         for(int i = 0; i < maxn; i++) {
41             G[i].clear();
42         }
43         for(int i = 1; i <= n; i++) {
44             scanf("%d", &x);
45             for(int j = 2; j * j <= x; j++) {
46                 if(x % j == 0) {
47                     while(x % j == 0) {
48                         G[j].push_back(i);
49                         x /= j;
50                     }
51                 }
52             }
53             if(x > 1) {
54                 G[x].push_back(i);
55             }
56         }
57         while(m--) {
58             scanf("%d%d%d", &l, &r, &d);
59             printf("%s
", slove(l, r, d) ? "Yes" : "No");
60         }
61     }
62 }
原文地址:https://www.cnblogs.com/Dillonh/p/9105038.html