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

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

小Q迅速地回答了出来,但是小T并不知道正确答案是什么,请写一个程序帮助小T计算这些问题的正确答案。

Input第一行包含一个正整数T(1≤T≤10)T(1≤T≤10),表示测试数据的组数。

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

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

接下来mm行,每行三个正整数l,r,d(1≤l≤r≤n,1≤d≤100000)l,r,d(1≤l≤r≤n,1≤d≤100000),表示每个问题。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

思路参考链接:https://blog.csdn.net/wjmwsgj/article/details/80519183

对于一个数(k)是不是d的倍数这类问题,我们可以对这两个数分解质因数,之后看看k的质因数和d的质因数之间的关系,如果满足对于d的每一个质因数个数,在k中都有出现过,且k的出现次数要大于等于d的出现次数,这个就是满足的,举个例子,36 和 6 ,36的质因数有 2,2,3,3,6的质因数有 2,3,其中36中2出现的次数大于了6中2出现的次数,36中3出现的次数大于了6中3出现的次数,故36是6的倍数。

那么对于这道题,我们需要做的就是先将这n个数分解质因数,对于区间问题我们要怎么解决呢?我们把质因数出现的位置给存下来,比如说我们现在在第3个数,a[3] = 8 ,那么我们开一个vector w[2]里加入 3,3,3,3,(相当于w[2]里面记录的是2这个质因子是下标为2这个数的因子)之后,之后比如说我们现在要查询l,r的区间是不是d的倍数,我们将d分解质因数之后用二分去查询我们当前的区间里有没有这个值就好了。

刚开始用的质因子分解方法复杂度太大,导致TLE

 1 const int maxn=100005;
2 vector<int>w[maxn];
3 int maxx=0;
4 bool isprim(int x)
5 {
6 for(int i=2; i<=sqrt(x); ++i)
7 {
8 if(x%i==0) return 0;
9 }
10 return 1;
11 }
12 void digui(int x,int id)
13 {
14 int temp=sqrt(x);
15 if(isprim(x))
16 w[x].push_back(id),maxx=max(maxx,x);
17 else
18 {
19 for(int i=2; i<=temp; ++i) //这个for循环作用就是找一个x的因子
20 {
21 if(x%i==0)
22 {
23 digui(i,id);
24 digui(x/i,id);
25 }
26 }
27 }
28 }

TLE全部代码:

 1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 #include<math.h>
6 #include<vector>
7 using namespace std;
8 typedef long long ll;
9 const int maxn=100005;
10 vector<int>w[maxn];
11 int maxx=0;
12 bool isprim(int x)
13 {
14 for(int i=2; i<=sqrt(x); ++i)
15 {
16 if(x%i==0) return 0;
17 }
18 return 1;
19 }
20 void digui(int x,int id)
21 {
22 int temp=sqrt(x);
23 if(isprim(x))
24 w[x].push_back(id),maxx=max(maxx,x);
25 else
26 {
27 for(int i=2; i<=temp; ++i) //这个for循环作用就是找一个x的因子
28 {
29 if(x%i==0)
30 {
31 digui(i,id);
32 digui(x/i,id);
33 }
34 }
35 }
36 }
37 int main()
38 {
39 int t;
40 scanf("%d",&t);
41 while(t--)
42 {
43 maxx=0;
44 int n,m;
45 scanf("%d%d",&n,&m);
46 for(int i=0;i<maxn;i++)
47 w[i].clear();
48 for(int i=0;i<n;++i)
49 {
50 int x;
51 scanf("%d",&x);
52 digui(x,i);
53 }
54 // for(int i=0;i<maxx;i++)
55 // sort(w,w+w[i].size());
56 while(m--)
57 {
58 int flag=0,l,r,d;
59 scanf("%d%d%d",&l,&r,&d);
60 l--,r--;
61 for(int i=2;i<=sqrt(d);++i)
62 {
63 int num=0;
64 while(d%i==0)
65 d/=i,num++;
66 if(num)
67 {
68 int pos=upper_bound(w[i].begin(),w[i].end(),r)-lower_bound(w[i].begin() , w[i].end(),l);
69 if(pos < num) //如果小于我们现在需要的,就说明不行。
70 {
71 flag=1;
72 break;
73 }
74 }
75 }
76 if(d>1) //同理
77 {
78 int pos=upper_bound(w[d].begin(),w[d].end(),r)-lower_bound(w[d].begin() , w[d].end(),l);
79 if(pos==0) flag=1;
80 }
81 if(flag)
82 {
83 printf("No\n");
84 }
85 else
86 {
87 printf("Yes\n");
88 }
89 }
90 }
91 return 0;
92 }

实际上不需要用isprim来判断某个数是不是素数

看下面一种方法:

 1 const int maxn=100005;
2 vector<int>w[maxn];
3 int maxx=0;
4 void resolve(int x,int id)
5 {
6 for(int i = 2 ; i * i <= x ; i++) // 这里的i最大是313
7 {
8 while(x % i == 0) //一直除的话就不会遇到i是合数的情况
9 {
10 w[i].push_back(id);
11 x = x/i;
12 }
13 }
14 if(x>1) // 这里有一个问题就是 我sqrt(maxn)里的最大的质数其实是313,那么我来了一个2 * 313的时候,我们找到的质因数只有2 ,所以当他没有到1的时候说明我们没有完
15 {
16 w[x].push_back(id); // 需要在搞一下
17 }
18 }

正确代码:

  1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 #include<math.h>
6 #include<vector>
7 using namespace std;
8 typedef long long ll;
9 const int maxn=100005;
10 vector<int>w[maxn];
11 int maxx=0;
12 void resolve(int x,int id)
13 {
14 for(int i = 2 ; i * i <= x ; i++) // 这里的i最大是313
15 {
16 while(x % i == 0) //一直除的话就不会遇到i是合数的情况
17 {
18 w[i].push_back(id);
19 x = x/i;
20 }
21 }
22 if(x>1) // 这里有一个问题就是 我sqrt(maxn)里的最大的质数其实是313,那么我来了一个2 * 313的时候,我们找到的质因数只有2 ,所以当他没有到1的时候说明我们没有完
23 {
24 w[x].push_back(id); // 需要在搞一下
25 }
26 }
27 /*这一种质因数分解太耗时了*/
28 //bool isprim(int x)
29 //{
30 // for(int i=2; i<=sqrt(x); ++i)
31 // {
32 // if(x%i==0) return 0;
33 // }
34 // return 1;
35 //}
36 //void digui(int x,int id)
37 //{
38 // int temp=sqrt(x);
39 // if(isprim(x))
40 // w[x].push_back(id),maxx=max(maxx,x);
41 // else
42 // {
43 // for(int i=2; i<=temp; ++i) //这个for循环作用就是找一个x的因子
44 // {
45 // if(x%i==0)
46 // {
47 // digui(i,id);
48 // digui(x/i,id);
49 // }
50 // }
51 // }
52 //}
53 int main()
54 {
55 int t;
56 scanf("%d",&t);
57 while(t--)
58 {
59 maxx=0;
60 int n,m;
61 scanf("%d%d",&n,&m);
62 for(int i=0;i<maxn;i++)
63 w[i].clear();
64 for(int i=0;i<n;++i)
65 {
66 int x;
67 scanf("%d",&x);
68 //digui(x,i);
69 resolve(x,i);
70 }
71 // for(int i=0;i<maxx;i++)
72 // sort(w,w+w[i].size());
73 while(m--)
74 {
75 int flag=0,l,r,d;
76 scanf("%d%d%d",&l,&r,&d);
77 l--,r--;
78 for(int i=2;i<=sqrt(d);++i)
79 {
80 int num=0;
81 while(d%i==0)
82 d/=i,num++;
83 if(num)
84 {
85 //upper_bound是找到大于r的
86 //low_bound是找到大于等于l的
87 int pos=upper_bound(w[i].begin(),w[i].end(),r)-lower_bound(w[i].begin() , w[i].end(),l);
88 if(pos < num) //如果小于我们现在需要的,就说明不行。
89 {
90 flag=1;
91 break;
92 }
93 }
94 }
95 if(d>1) //同理
96 {
97 int pos=upper_bound(w[d].begin(),w[d].end(),r)-lower_bound(w[d].begin() , w[d].end(),l);
98 if(pos==0) flag=1;
99 }
100 if(flag)
101 {
102 printf("No\n");
103 }
104 else
105 {
106 printf("Yes\n");
107 }
108 }
109 }
110 return 0;
111 }

最新文章

  1. Android studio 如何查看当前git 分支的4种方式
  2. regsvr32的使用
  3. java https tomcat 单双认证(含证书生成和代码实现) 原创转载请备注,谢谢O(∩_∩)O
  4. ios开发之CoreData使用
  5. ASP.NET之AreaRegistration
  6. vector中的元素删除
  7. java使用redis
  8. vue.js应用开发笔记
  9. Node.js安装和配置
  10. 201521123062《Java程序设计》第8周学习总结
  11. VS报错 error LNK2005: _DllMain@12 已经在 MSVCRTD.lib(dllmain.obj) 中定义
  12. day17递归函数(二分法查找)
  13. GIT回滚master分支到指定tag版本
  14. Tornado的异步非阻塞
  15. shell中的ps命令详解
  16. 1490 ACM 数学
  17. linux中VI编写C程序。。。
  18. linux-IO重定向-文本流重定向
  19. 【转载】JAVA消息服务JMS规范及原理详解
  20. Tarjan缩点求入度为零的点的个数问题

热门文章

  1. 如何实现CentOS服务器的扩容??
  2. 如何实现一个简易版的 Spring - 如何实现 Constructor 注入
  3. JavaScript中的原型、原型链、原型模式
  4. 【Oracle】删除(释放)数据文件/表空间流程
  5. 代码审计 - BugkuCTF
  6. ctfhub技能树—sql注入—时间盲注
  7. linux GPU上多个buffer间的同步 —— ww_mutex、dma-fence的使用 笔记
  8. has been blocked by CORS policy: Response to preflight request doesn&#39;t pass access control check: No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource.
  9. cookie中的domain和path
  10. C++ Primer Plus读书笔记(八)函数探幽