【hdu】口算訓練/二分/質因數分解

Qianzhez。發表於2020-09-23

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中國大學生程式設計競賽-女生專場

【題解】:
1.某個數x能被y整除,就是將兩個數進行質因數分解,然後比較分解出每個質因數的個數,如果x的全部都小於等於y的,那麼x就能被y整除。
2.這裡的思路也是類似,把給出的一列數字逐個質因數分解,分解結果用vector< int > f[]來存,f【i】就表示能分解出質因數i的數有哪些。
3.因為質因數的陣列,是根據輸入逐個輸入的,所以儲存結果必然是有順序的,所以查詢l,r中有多少這個質因數就完全可以用二分法,這裡用的是stl裡面的lower_bound 和 upper_bound ,然後比較個數
4.注意:分解質因數的步驟除了列舉之外,還要單獨判斷是否已經被分解成為1了
5.注意儲存質因數的陣列要初始化

程式碼

#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
vector<int> f[maxn];//儲存分解的質因數
void fj(int id,int x)
{
    for(int i=2;i*i<=x;i++)
    {
        while(x%i==0)
        {
            f[i].push_back(id);
            x=x/i;
        }
    }
    if(x>1)//注意特判
        f[x].push_back(id);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        for(int i=0;i<maxn;i++)
        {
            f[i].clear();
        }
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            int a;
            scanf("%d",&a);
            fj(i,a);
        }
        for(int i=0;i<m;i++)
        {
            int l,r,d;
            scanf("%d%d%d",&l,&r,&d);
            l--;
            r--;

            int flg=0;
            for(int j=2;j*j<=d;j++)
            {
                 int cnt=0;
                while(d%j==0)
                {
                    cnt++;
                    d=d/j;
                }
                if(cnt)
                {
                    int pos=upper_bound(f[j].begin(),f[j].end(),r)-lower_bound(f[j].begin(),f[j].end(),l);
                    if(cnt>pos)
                    {
                        flg=1;
                        break;
                    }
                }
            }
            if(d>1)
            {
                int pos=upper_bound(f[d].begin(),f[d].end(),r)-lower_bound(f[d].begin(),f[d].end(),l);//二分法
                if(pos==0)
                    flg=1;
            }
            if(flg==1)
                printf("No\n");
            else
                printf("Yes\n");
        }

    }
    return 0;

}

相關文章