小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 }

HDU - 6287 口算训练 二分+质因数分解的更多相关文章

  1. hdu 6287 口算训练

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

  2. [BZOJ5358]/[HDU6287]口算训练

    [BZOJ5358]/[HDU6287]口算训练 题目大意: 给定一个长度为\(n(n\le10^5)\)的正整数序列\(a_{1\sim n}\),\(m(m\le10^5)\)次询问.每次询问给出 ...

  3. C# WinForm动态控件实例:口算训练

    昨天晚上回寝室看到室友正在被一个C#课的作业苦恼,作业的内容是编写一个口算训练程序,能够实现随意添加题目数量.于是,喜欢写C#的我就决定解救一下他们. 创建动态控件 既然要动态添加,那就必须使用动态控 ...

  4. [Bzoj5358][Lydsy1805月赛]口算训练(预处理+动态开点线段树)

    5358: [Lydsy1805月赛]口算训练 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 318  Solved: 105[Submit][Stat ...

  5. 2018 CCPC 女生赛 hdoj6287 口算训练

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6287 Summarize: 1.分解质因数: 2.二分查找函数lower_bound与upper_bo ...

  6. [Lydsy1805月赛]口算训练 BZOJ5358

    分析: 没想到这道题还能二分查找... 这题主席树的话,裸的很显然...我们将每一个数分解质因数,之后建一个可持久化权值线段树维护[L,R]区间内的每一种质因子的个数,分解质因数的话,可以选择用线筛, ...

  7. WPF简单的口算案例

    前几天在博客园,看到有博友利用Winform做了一个口算案例,于是我想把它移植在WPF程序中.Winform程序:http://www.cnblogs.com/ImYZF/p/3345452.html ...

  8. POJ 1845 Sumdiv#质因数分解+二分

    题目链接:http://poj.org/problem?id=1845 关于质因数分解,模板见:http://www.cnblogs.com/atmacmer/p/5285810.html 二分法思想 ...

  9. 【(阶乘的质因数分解)算组合数】【TOJ4111】【Binomial efficient】

    n<=10^6 m<=10^6 p=2^32 用unsigned int 可以避免取模 我写的SB超时 阶乘分解代码 #include <cstdio> #include &l ...

随机推荐

  1. Sentry(v20.12.1) K8S 云原生架构探索,SENTRY FOR JAVASCRIPT 故障排除

    系列 Sentry-Go SDK 中文实践指南 一起来刷 Sentry For Go 官方文档之 Enriching Events Snuba:Sentry 新的搜索基础设施(基于 ClickHous ...

  2. 【Linux】同时插入多行数据到文本文件中

    如果想同时插入多行数据到指定的文本中,可以用下面的命令EOF cat >> test.txt <<EOF 1234 5678 GOOD EOF 将上述3行插入到 test.tx ...

  3. 【MySQL】ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing

    今天上午遇到了一个问题,新创建的mysql5.7的数据库,由于初始化有点问题,没有给root密码,用了免密码登录. 但是,修改了root密码之后,把配置中的免密登录的配置注释掉后,重启服务.服务正常启 ...

  4. XSS - Pikachu

    概述: Cross-Site Scripting 简称为"CSS",为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS.一般XSS可以分为如下几种常见类型 ...

  5. Poj-P3468题解【线段树】

    本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/ 题目出处: http://poj.org/problem?id=3468 题目描述: 给N个数A1, A2 ...

  6. 从零搭建一个IdentityServer——项目搭建

    本篇文章是基于ASP.NET CORE 5.0以及IdentityServer4的IdentityServer搭建,为什么要从零搭建呢?IdentityServer4本身就有很多模板可以直接生成一个可 ...

  7. SpringMVC Tomcat 启动时报错:java.lang.IllegalStateException: Error starting child

    大概原因如下: 1.Controller里RequestMapping("/test")前面没有"/"; 2.jar包冲突,比如我的将数据库连接版本由5.1.6 ...

  8. 当中台遇上DDD,我们该如何设计微服务? - InfoQ https://www.infoq.cn/article/7QgXyp4Jh3-5Pk6LydWw

    当中台遇上DDD,我们该如何设计微服务? - InfoQ https://www.infoq.cn/article/7QgXyp4Jh3-5Pk6LydWw

  9. nothreading use single threaded

    threading:   # ThreadingMixIn.daemon_threads indicates how threads will behave on an   # abrupt shut ...

  10. __del__ PyPy和CPython的不同点 动态编译(注意不是解释) 析构函数被调用的次数

    小结 1.cpy的垃圾回收会对调用__del__多次:pypy仅仅一次: https://www.liaoxuefeng.com/wiki/1016959663602400/1016966024263 ...