Uva 10539 Almost Prime Numbers
题意:寻找特定区间内满足本身不是素数,但只有一个素因子的数。
这道题我一开始做了个超时(交的时候又忘记了测试大数。。。)。我原先是打算正向计算,对于每一个数判断他是否是素数,是否是只有一个素因子。这种思路能做,只是算法时间复杂度不符合题目要求。原题数组组数有几百,最大的数有10^12...
通过这个题目,我得到两个经验:
遇到特别大的数,八成是要打表做。
正向想不通的,逆向做或许更简单。
先找出所有素数,根据素数构造所有满足条件的数是这道题的可行思路。
因为素数的二次方以及以上一定不是素数并且只有一个素因子,只要保证这个数小于10^12,所以我们可以从表中查找我们输入的值。因为数据量比较大,我们排序后用二分查找寻找上下界,相减就是结果。
另外,注意我这里用的求素数的方法。这种方法比较高效。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int smaxn = 1000000; 4 vector<long long > notprime; 5 bool vis[smaxn +1] ={false}; 6 int primes[smaxn]; 7 const long long int maxn = 1000000000000LL; 8 void store_prime(){ 9 int cnt = 0; 10 int m = (int )sqrt(smaxn + 0.5); 11 for(int i = 2; i<=m;i++)if(!vis[i]) 12 for(int j = i*i; j <=smaxn;j+=i)vis[j] = 1; 13 for(int i=2;i<=smaxn;i++)if(!vis[i])primes[cnt++] = i; 14 for(int i =0; i< cnt;i++){ 15 long long d = primes[i]; 16 while(1){ 17 d*=primes[i]; 18 if(d >= maxn) break; 19 notprime.push_back(d); 20 } 21 } 22 } 23 int main(){ 24 int n; 25 store_prime(); 26 sort(notprime.begin(),notprime.end()); 27 scanf("%d",&n); 28 while(n--){ 29 long long L, U; 30 scanf("%lld%lld",&L,&U); 31 long long a = upper_bound(notprime.begin(),notprime.end(),U) -notprime.begin() ; 32 long long b = lower_bound(notprime.begin(),notprime.end(),L) -notprime.begin() ; 33 printf("%lld\n",a-b); 34 } 35 return 0; 36 }