码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 6287 口算训练

时间:2018-06-11 02:01:46      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:pre   是什么   math   scan   大于等于   element   数学   开始   include   

题意:

小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计算这些问题的正确答案。

思路:

一开始bit套map 用前缀和处理,tle了?

对于每一个输入的数字,分解质因子,对于每一个质因子,把这个数字的位置push到这个质因子的vector里面去。

那么每一个vector里面的数字就是非递减的了。

然后对于每一个输入的l,r,d,把d分解质因子,对于每一个质因子,在这个质因子的vector里面找第一个大于等于l的位置和最后一个小于等于r的位置,相减,比较是否有d中这个质因子的数量多。

找的时候当然利用前面的非递减,所以可以二分。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <vector>
  5 using namespace std;
  6 const int N = 1e5 + 10;
  7 
  8 vector<int> p;
  9 vector<int> G[N],g[N];
 10 bool pp[N];
 11 int a[N];
 12 int n,m;
 13 
 14 int main()
 15 {
 16     for (int i = 2;i < N;i++)
 17     {
 18         if (!pp[i])
 19         {
 20             p.push_back(i);
 21             for (int j = i * 2;j < N;j += i)
 22             {
 23                 G[j].push_back(i);
 24                 pp[j] = 1;
 25             }
 26         }
 27     }
 28     int T;
 29     scanf("%d",&T);
 30     while (T--)
 31     {
 32         scanf("%d%d",&n,&m);
 33         for (int i = 0;i < p.size();i++)
 34         {
 35             g[p[i]].clear();
 36         }
 37         for (int i = 1;i <= n;i++)
 38         {
 39             int x;
 40             scanf("%d",&x);
 41             if (x == 1) continue;
 42             if (!pp[x])
 43             {
 44                 g[x].push_back(i);
 45                 continue;
 46             }
 47             for (int j = 0;j < G[x].size();j++)
 48             {
 49                 int cnt = 0;
 50                 int tmp = x;
 51                 int v = G[x][j];
 52                 while (tmp % v == 0)
 53                 {
 54                     tmp /= v;
 55                     g[v].push_back(i);
 56                 }
 57             }
 58         }
 59         while (m--)
 60         {
 61             int l,r,d;
 62             scanf("%d%d%d",&l,&r,&d);
 63             if (d == 1)
 64             {
 65                 puts("Yes");
 66                 continue;
 67             }
 68             if (!pp[d])
 69             {
 70                 int x = lower_bound(g[d].begin(),g[d].end(),l) - g[d].begin();
 71                 int y = upper_bound(g[d].begin(),g[d].end(),r) - g[d].begin();
 72                 y--;
 73                 if (y - x + 1 < 1) puts("No");
 74                 else puts("Yes");
 75             }
 76             else
 77             {
 78                 bool f = 0;
 79                 for (int i = 0;i < G[d].size();i++)
 80                 {
 81                     int v = G[d][i];
 82                     int cnt = 0;
 83                     int tmp = d;
 84                     while (tmp % v == 0)
 85                     {
 86                         cnt++;
 87                         tmp /= v;
 88                     }
 89                     int x = lower_bound(g[v].begin(),g[v].end(),l) - g[v].begin();
 90                     int y = upper_bound(g[v].begin(),g[v].end(),r) - g[v].begin();
 91                     y--;
 92                     if (y - x + 1 < cnt) f = 1;
 93                     if (f) break;
 94                 }
 95                 if (f) puts("No");
 96                 else puts("Yes");
 97             }
 98         }
 99     }
100     return 0;
101 }

 

hdu 6287 口算训练

标签:pre   是什么   math   scan   大于等于   element   数学   开始   include   

原文地址:https://www.cnblogs.com/kickit/p/9165166.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!