HDU6287:口算训练(莫队算法)

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

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

小Q迅速地回答了出来,但是小T并不知道正确答案是什么,请写一个程序帮助小T计算这些问题的正确答案。
Input第一行包含一个正整数 T(1T10)T(1≤T≤10),表示测试数据的组数。 

每组数据第一行包含两个正整数 n,m(1n,m100000)n,m(1≤n,m≤100000),分别表示序列长度以及问题个数。 

第二行包含 nn个正整数 a1,a2,...,an(1ai100000)a1,a2,...,an(1≤ai≤100000),表示序列中的每个数。 

接下来 mm行,每行三个正整数 l,r,d(1lrn,1d100000)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

思路:朴素的想法对N个数分解质因子分别维护前缀和,但是100000范围素数有点多时间不允许,容易发现每个数>sqrt(100000)的质因子至多有一个,那么单独处理这一个就行了,可以用莫队维护或者二分。

# include 
# include 
# include 
# include 
using namespace std;
typedef long long LL;
const int maxn = 1e5+30;
int p[maxn], cnt=0, vis[maxn], tot[maxn]={0}, len;
int a[maxn], val[maxn], sum[maxn][66], id[maxn];
int ans[maxn];
inline void scan(int &ret)
{
    ret = 0;
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9') ret = ret * 10 + (c - '0'), c = getchar();
}
void init()
{
    int up = (int)sqrt(100000);
    for(int i=2; i<=up; ++i)
    {
        if(vis[i] == 0)
        {
            p[++cnt] = i;
            id[i] = cnt;
            for(int j=i+i; j<=up; j+=i)
                vis[j] = 1;
        }
    }
}
struct node
{
    int l, r, id, fk, block;
    node(){}
    node(int l, int r, int fk, int id):l(l),r(r),fk(fk), id(id){block=l/len;}
    bool operator <(const node b) const
    {
        if(block == b.block) return rl)
            {
                --L;
                ++tot[val[L]];
            }
            while(R>r)
            {
                --tot[val[R]];
                --R;
            }
            while(L


你可能感兴趣的:(数论)