口算训练Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Total Submission(s): 2263 Accepted Submission(s): 504 Problem Description 小Q非常喜欢数学,但是他的口算能力非常弱。因此他找到了小T,给了小T一个长度为n 的正整数序列a1,a2,...,an ,要求小T抛出m 个问题以训练他的口算能力。 Input 第一行包含一个正整数T(1≤T≤10) ,表示测试数据的组数。 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 Source |
【解题思路】
判断一个数是否被另一个整除,可以将两个数都质因数分解,比如判断a是否能被b整除,b分解质因数之后所有的质因数都能在a中找到,并且<=a中该质因数的个数,说明a%b==0。
所以本题可以用这个思路,将n个数都质因数分解,用vector v[maxn]存储质因数,下标为质因数,然后将每个n个数对应的下标压入v中,最后用二分计算l,r的区间中质因数的个数作比较即可。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
vector<int>v[maxn];
void f(int index,int x)
{
for(int i=2;i<=sqrt(x);i++)
{
while(x%i==0)
{
v[i].push_back(index);
x/=i;
}
}
if(x>1)v[x].push_back(index);//当这个数本身就是质数
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=0;i<maxn;i++)v[i].clear();
int n,m,x;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
f(i,x);
}
while(m--)
{
int l,r,d,flag=1;
scanf("%d%d%d",&l,&r,&d);
for(int i=2;i<=sqrt(d);i++)
{
int cnt=0;
while(d%i==0)
{
cnt++;
d/=i;
}
if(cnt)
{
int pos=upper_bound(v[i].begin(),v[i].end(),r)-lower_bound(v[i].begin(),v[i].end(),l);
if(pos<cnt)
{
flag=0;
break;
}
}
}
if(d>1)
{
int pos=upper_bound(v[d].begin(),v[d].end(),r)-lower_bound(v[d].begin(),v[d].end(),l);
if(pos==0)flag=0;
}
if(flag)printf("Yes\n");
else printf("No\n");
}
}
return 0;
}