线性筛素数——Homework(2015 Facebook Hacker Cup)

来源:互联网 发布:攻击ip软件 编辑:程序博客网 时间:2024/06/06 03:40

题目:
Your first-grade math teacher, Mr. Book, has just introduced you to an amazing new concept — primes! According to your notes, a prime is a positive integer greater than 1 that is divisible by only 1 and itself.
Primes seem fun, but without giving you and your 6-year-old colleagues time to consider their implications, he’s promptly gone on to define another term: primacity. He explains that the primacity of an integer is the number of distinct primes which divide it. For example, the primacity of 12 is 2 (as it’s divisible by primes 2 and 3), the primacity of 550 is 3 (as it’s divisible by primes 2, 5, and 11), and the primacity of 7 is 1 (as the only prime it’s divisible by is 7).
Following his lesson, Mr. Book has given you homework with some rather mean questions of the following form: Given 3 integers A, B, and K, how many integers in the inclusive range [A, B] have a primacity of exactly K?
Mr. Book probably expects his little homework assignment to take you and your classmates the rest of the year to complete, giving him time to slack off and nap during the remaining math classes. However, you want to learn more things from him instead! Can you use the skills you’ve learned in your first-grade computer science classes to finish Mr. Book’s homework before tomorrow’s math class?

输入:
Input begins with an integer T, the number of homework questions. For each question, there is one line containing 3 space-separated integers:A, B, and K.

输出:
For the ith question, print a line containing “Case #i: ” followed by the number of integers in the inclusive range [A, B] with a primacity of K.

范围:
1 ≤ T ≤ 100
2 ≤ A ≤ B ≤ 107
1 ≤ K ≤ 109

Sample Input
5
5 15 2
2 10 1
24 42 3
1000000 1000000 1
1000000 1000000 2

Sample Output
Case #1: 5
Case #2: 7
Case #3: 2
Case #4: 0
Case #5: 1

题解:
第一种方法,一开始直接模拟做,求出每个数由多少个素数组成,结果自然TLE。

TLE代码:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;int dp[12345678];int K;bool isPrime (int num){    if(dp[num] == 1)    {        return true;    }    if(dp[num] == -1)    {        return false;    }    for(int i=2;i*i<=num;i++)    {        if(num%i == 0)        {            dp[num] = -1;            return false;        }    }    dp[num] = 1;    return true;}int primacity(int num){    int cnt = 0;    for(int i =2 ; i*i<=num;i++)    {        if(num%i==0)        {            if(isPrime(i) )            {                cnt++;                //cout << i << endl;            }            if(isPrime(num/i)&& (num/i) !=i&&(num/i)<=num/2)            {                cnt++;                //cout << num/i << endl;            }        }    }    if(isPrime(num))    {        cnt++;        //cout << num << endl;    }    //cout << num << ":" << cnt << endl;    return cnt;}int main(){    int T;    int t=1;    cin >> T;    int A,B;    while(t<=T)    {        scanf("%d%d%d", &A, &B, &K);        int ans=0;        for(int i=A; i<=B;i++)        {            if(primacity(i) == K)            {                //cout << i  << ":" << primacity(i) << endl;                ans++;            }        }        cout << "Case #" << t++ << ": " << ans << endl;    }}

第二种方法:
线性筛素数,因为根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积,最小的质数是2。
所以可以直接求出每个素数的倍数:建立一个题目制定范围大小的数组,从2 开始如果那个数代表的下标指向内存为0就从2开始乘一遍,得出的数作为下标,指向的内存+1,代表该下标表示的数含有一个素数(第一遍的素数是2),然后最外层++,如果最外层数下标指向的内存为0,说明该下标即是素数,再对它从2开始乘一遍,如果不为0,说明该数是合数,跳过。
这种线性筛素数的方法,时间复杂度非常低,除第一遍计算整个数组后,之后的操作是直接查询。

AC代码:

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int INF = 10000010;int KK[INF];int K;void primacity(){    for(int i=2;i<=INF; i++)    {        if( !KK[i])        {            KK[i]++;            for(int j=2; i*j<=INF;j++)            {                KK[i*j]++;            }        }    }}int main(){    primacity();    int T;    int t=1;    cin >> T;    int A,B;    while(t<=T)    {        scanf("%d%d%d", &A, &B, &K);        int ans=0;        for(int i=A; i<=B;i++)        {            if(KK[i] == K)            {                //cout << i  << ":" << primacity(i) << endl;                ans++;            }        }        cout << "Case #" << t++ << ": " << ans << endl;    }}
0 0