Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 6517 Accepted Submission(s): 1423
我们可以将所有数字进行素因子分解,如 6 4 他们的乘积可以分解为2^3*3^1,而 24 同样可以备份分解为 2^3*3^1 显然,当询问的数字分解的素因子均存在与区间乘积的分解后的因子中,且区间乘积分解的任意因子的次幂均不小于询问的数字分解的素因子的次幂时,区间乘积就一定被所询问的数字整除
但这里有一个难点:我们如何存储分解出来的素因子及其次幂,同时还能方便后续的查找呢?
这里提供一个方法:vector
G[i] 内的信息表示素因子 i 出现的位置
如: 6 4
则 G[2]={1,2,2} //素因子 1 出现在第一个位置,由于位置只有一个 1 个,所以在位置1只出现了一次;素因子 2 出现在第一个位置,由于位置只有一个 2 个,所以在位置 2 只出现了两次
G[3]={1} //素因子 3 出现在第一个位置,由于位置只有一个 1 个,所以在位置1只出现了一次
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
- typedef long long LL;
- const int N = 1e5 + 5;
- int n,m;
- int a[N];
- int l, r, d;
- vector<int>G[N];
-
- void F(int t, int index) {
- for (int i = 2; i * i <= t; i++) {
- while (t % i == 0) {
- G[i].push_back(index);
- t /= i;
- }
- }
- if (t>1) {
- G[t].push_back(index);
- }
- }
-
- int main() {
- int T;
- scanf("%d", &T);
- while (T--) {
- scanf("%d%d", &n, &m);
- for (int i = 1; i < N; i++)G[i].clear();
- for (int i = 1,t; i <= n; i++) {
- scanf("%d", &t);
- F(t,i);
- }
- while (m--) {
- int flg = 0,cnt=0;
- scanf("%d%d%d", &l, &r, &d);
- for (int i = 2; i * i <= d; i++) {
- cnt = 0;
- while (d % i == 0) {
- d /= i;
- cnt++;
- }
- if (cnt) {//千万注意,不能少这个判断,否则会多出很多无意义的运行,回爆时间
- //lower_bound 返回一个迭代器,指向序列中不小于给定值的第一个元素。
- //upper_bound 返回一个迭代器,指向序列中大于给定值的第一个元素。
- int pp = upper_bound(G[i].begin(), G[i].end(), r) - lower_bound(G[i].begin(), G[i].end(), l);
- if (pp < cnt) {
- flg = 1;
- break;
- }
- }
- }
- if (d > 1) {
- int pp = upper_bound(G[d].begin(), G[d].end(), r) - lower_bound(G[d].begin(), G[d].end(), l);
- if (!pp) {
- flg = 1;
- }
- }
- if (flg) {
- printf("No\n");
- }
- else {
- printf("Yes\n");
- }
- }
- }
- return 0;
- }