口算训练
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Total Submission(s): 1363 Accepted Submission(s): 275
Problem Description
小Q非常喜欢数学,但是他的口算能力非常弱。因此他找到了小T,给了小T一个长度为
n的正整数序列
a1,a2,...,an,要求小T抛出
m个问题以训练他的口算能力。
每个问题给出三个正整数 l,r,d,小Q需要通过口算快速判断 al×al+1×...×ar−1×ar 是不是 d的倍数。
每个问题给出三个正整数 l,r,d,小Q需要通过口算快速判断 al×al+1×...×ar−1×ar 是不是 d的倍数。
l->r之间数的乘积是不是d的倍数
小Q迅速地回答了出来,但是小T并不知道正确答案是什么,请写一个程序帮助小T计算这些问题的正确答案。
小Q迅速地回答了出来,但是小T并不知道正确答案是什么,请写一个程序帮助小T计算这些问题的正确答案。
Input
第一行包含一个正整数
T(1≤T≤10),表示测试数据的组数。
每组数据第一行包含两个正整数 n,m(1≤n,m≤100000),分别表示序列长度以及问题个数。
第二行包含 n个正整数 a1,a2,...,an(1≤ai≤100000),表示序列中的每个数。
接下来 m行,每行三个正整数 l,r,d(1≤l≤r≤n,1≤d≤100000),表示每个问题。
每组数据第一行包含两个正整数 n,m(1≤n,m≤100000),分别表示序列长度以及问题个数。
第二行包含 n个正整数 a1,a2,...,an(1≤ai≤100000),表示序列中的每个数。
接下来 m行,每行三个正整数 l,r,d(1≤l≤r≤n,1≤d≤100000),表示每个问题。
Output
对于每个问题输出一行,若是倍数,输出Yes,否则输出No。
Sample Input
15 46 4 7 2 51 2 241 3 182 5 173 5 35
Sample Output
YesNoNoYes
Source
记录每一个质数存在的下标,比如数据 2 4 8 16 那么v[2]={1,2,2,3,3,3,4,4,4,4}; 表示2这个质数在数据中出现的下标。用vector可以实现。查询之前先处理好每个质数的数组 那么查询[l,r]=[2,4]中, 有2的多少次方: upper_bound(v[2].begin(),v[2].end(),r)-lower_bound(v[2].begin(),v[2].end(),l) 查找返回的是下标 所以相减后就是该质数在该区间出现的次数 答案是9,表示l到r之间最多能够组成2的9次方; 对查询中的数d进行质因数分解,再逐个质因数进行查询即可解决。 对某个数进行质因数分解时,分解过程中若a为质数,则跳出循环,不然会卡时间 |
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7;
vector<int>v[maxn];
int prime[maxn],cnt=0;
void init(){
memset(prime,0,sizeof(prime));
for(int i=2;i<=maxn;i++){
if(!prime[i]) prime[cnt++]=i;
for(int j=0;j<cnt;j++){
if(i*prime[j]>=maxn) break;
prime[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
bool ac(int l,int r,int d){
for(int i=0;i<cnt&&prime[i]*prime[i]<=d;i++){
int cnt=0;
while(d%prime[i]==0) cnt++,d/=prime[i];
int prime_num=upper_bound(v[prime[i]].begin(),v[prime[i]].end(),r)-lower_bound(v[prime[i]].begin(),v[prime[i]].end(),l);
if(cnt>prime_num) return false;
}
if(d>1) {
int prime_num=upper_bound(v[d].begin(),v[d].end(),r)-lower_bound(v[d].begin(),v[d].end(),l);
if(prime_num<1) return false;
}
return true;
}
int val;
void solve(){
int n,m;scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&val);
for(int j=0;j<cnt&&prime[j]*prime[j]<=val;j++){
while(val%prime[j]==0) val/=prime[j],v[prime[j]].push_back(i);
}
if(val>1) v[val].push_back(i);
}
while(m--){
int l,r,d;
scanf("%d %d %d",&l,&r,&d);
puts(ac(l,r,d)?"Yes":"No");
}
}
int main(){
init();
int t;scanf("%d",&t);
while(t--) {
for(int i=0;i<maxn;i++) v[i].clear();
solve();
}
return 0;
}