HDU - 6287口算训练---二维数组vector+二分

题目链接:https://cn.vjudge.net/problem/HDU-6287

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

题目思路:如果暴力求解(al+...+ar)/d,数据内存肯定会超,所以数据肯定是要分解成因子判断的

思路一:先定义一个数组存不大于100000的素数,然后存al到ar每个元素所含有的素数次数,d肯定可以分解成m个素数相乘,那我们只需判断这m个素数j的次数是否不大于之前存的素数j的次数

代码:之前写了,找不到了。。。。结果是超时,思路可以解决问题,但是超时是解决不了的

正确思路:二分+vector二维数组

p[因子][元素a下标]

使用二维vector,n行m列,n是a[h]的因子个数,m存的是含因子i的a[h]元素下标j

比较d的每个因子,因子次数不大于a[l]到a[r]这因子个数总和

a[l]到a[r]这因子个数总和,我们可以用二分查找求得,vector的p[因子][元素a下标], lower_bound(p[i].begin(), p[i].end(), l)p[i]就是存因子i的二维数组,就是查找l的下标

upper_bound(p[i].begin(), p[i].end(), r)- lower_bound(p[i].begin(), p[i].end(), l)---------------这是查找区间[l,r]元素个数的正确姿势

代码:

#include
#include
#include
using namespace std;
vector<int> p[100005];
void shuru(int x,int i)
{
    for(int j=2;j*j<=x;j++)
    {
        while(x%j==0)
        {
            x/=j;
            p[j].push_back(i);//因子j,i下标 
        }
    }
    if(x>1)  //x可能是2,3 
    p[x].push_back(i);
}
bool solve(int l,int r,int d)
{
        int cnt;
        for(int i=2;i*i<=d;i++)
        {
        cnt=0;
        while(d%i==0)
        {
            d=d/i;
            cnt++;
        }
        
        if(cnt>0&&upper_bound(p[i].begin(),p[i].end(),r)-lower_bound(p[i].begin(),p[i].end(),l)//区间l,r含因子i的个数 
        {
            return 0;
        }
        }
        if(d>1&&upper_bound(p[d].begin(),p[d].end(),r)-lower_bound(p[d].begin(),p[d].end(),l)==0) //d可能是2,3 
        return 0;
        return 1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,l,r,d;
        for(int i=0;i<100005;i++)
        p[i].clear();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) 
        {
            int x;
            scanf("%d",&x);
            shuru(x,i);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&l,&r,&d);
            if(solve(l,r,d))
            printf("Yes\n");
            else
            printf("No\n");
        }
     }
}
View Code

 

总结:vector存元素注意存元素为0的情况,因为vector的元素大小也是默认为0 ,如果没注意,可能会因此产生错误。

比如该题,用a数组的下标存入vector二维数组中,既然下标要存入,那我们就设下标从一开始!!!

转载于:https://www.cnblogs.com/Aiahtwo/p/10875387.html

你可能感兴趣的:(HDU - 6287口算训练---二维数组vector+二分)