A - A HDU - 6287(质因数分解/普通因数分解)

时间:2020-04-20
本文章向大家介绍A - A HDU - 6287(质因数分解/普通因数分解),主要包括A - A HDU - 6287(质因数分解/普通因数分解)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

A - A HDU - 6287

题目链接

思路

题意

  • 给我一个长度为n长度乘法表达式\(a1*a2*a3*...*an\),又给我了\(a1 a2 ..an\) 相对应的值,给我们m次询问,每次询问给我们三个数 l、r、d, 表示意思是 \(al*al+1*...*ar\) 这段区间内的乘积(设其为x)能否是被 d整除?,再注意一下数据范围\(1=<ai<=1e5,n<=1e5,给的程序运行时间是4s\)

思路

  1. 首先直接求乘积会爆long long 肯定不行
  2. 给我们运行时间是4s,那么我们肯定是要经历一番计算的,我们考虑:如果一个数a能被另一个数b整除,那么a被分解成因子,b也被分解成因子,那么b因子一定是a因子集合的子集,接下来先补充一下质因子分解:任何一个数一个数都可以被分解成 一些质数的乘积
  3. 那么对于这一题,我们就可以把这个n个元素每一个都进行质因子分解,对于每一次询问我们都询问,我们都将d进行拆分,统计拆出来的质因子的数量进行统计,在与相应的\([l,r]\)区间内拆分拥有的值因子数量进行比较,如果d中的某个质因子的数量小与\([l,r]\)区间中的或者根本不存在的话,就输出No,,
  • 剩下关键就是统计每\([l,r]\)区间的值因子的数量:这个主要是通过声vector res[mxn] 这个容器,把某个数分解出来的质因子c作为下标,而res[c] 的值就是这个数的位置,这样相同的因子就在相同的容器中,这通过二分查找某个质因数的所在的位置

  • 对应区间的查找(这个实现主要是通 lower_boud 找下限、uppper_bound找上限),方法都很巧妙,

  • 其实这一题也可以不用质因子分解

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<stack>
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w",stdout); }
using namespace std;
const int mxn = 1e5 + 5;

vector<int> prime;
vector<int> res[mxn];

void Shai()
{
    int ar[mxn];
    for(int i = 2; i < mxn; i ++)
        ar[i] = 1;

    for(int i = 2; i < mxn; i ++)
    {
        if(i > mxn/i) break;
        if(ar[i])
        {
            for(int j = i * i; j < mxn; j += i)
                ar[j] = 0;
        }
    }
    for(int i = 2; i < mxn; i ++)
        if(ar[i])
            prime.push_back(i);
}

bool query(int l, int r, int val, int cnt)
{
    int tem = upper_bound(res[val].begin(), res[val].end(), r) - lower_bound(res[val].begin(), res[val].end(), l);    
    return tem >= cnt;
}

bool Solve(int l, int r, int d)
{
    //质因数分解d
    int cnt;        //相同质因子数量
    for(auto x : prime)
    {
        if(x*x > d) break;
        cnt = 0;
        while(d%x == 0 )
        {
            d /= x;
            cnt ++;
        }
        if(cnt >= 1 && ! query(l, r, x, cnt))
            return false;
    }
    if(d > 1 && ! query(l, r, d, 1))
        return false;
    return true;
}

void init()
{
    for(int i = 1; i < mxn; i ++)
        res[i].clear();
}

int main()
{
    /* fre(); */
    int t;
    scanf("%d", &t);
    Shai();
    while(t --)
    {
        init();
        int n, m;
        scanf("%d %d", &n, &m);
        int val;
        //对每一数进行质因数拆分
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d", &val);
            for(auto x : prime)
            {
                if(x*x > val) break;
                while(val%x == 0)
                {
                    val /= x;
                    res[x].push_back(i);
                }
            }
            if(val > 1)
                res[val].push_back(i);
        }
        int l, r, d;
        while(m --)
        {
            scanf("%d %d %d", &l, &r, &d);
            printf("%s\n", Solve(l, r, d) == true ? "Yes" : "No");
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/lql-nyist/p/12735978.html