【HDU6287】口算训练(思维+二分)

题目链接

口算训练

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 个问题以训练他的口算能力。

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

小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) ,表示每个问题。

 

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

"字节跳动杯"2018中国大学生程序设计竞赛-女生专场

【解题思路】

判断一个数是否被另一个整除,可以将两个数都质因数分解,比如判断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;
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/82852789