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\)
思路
- 首先直接求乘积会爆long long 肯定不行
- 给我们运行时间是4s,那么我们肯定是要经历一番计算的,我们考虑:如果一个数a能被另一个数b整除,那么a被分解成因子,b也被分解成因子,那么b因子一定是a因子集合的子集,接下来先补充一下质因子分解:任何一个数一个数都可以被分解成 一些质数的乘积
- 那么对于这一题,我们就可以把这个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;
}