Day7 - I - Semi-prime H-numbers POJ - 3292

This problem is based on an exercise of David Hilbert, who pedagogically suggested that one study the theory of 4n+1 numbers. Here, we do only a bit of that.

An H-number is a positive number which is one more than a multiple of four: 1, 5, 9, 13, 17, 21,... are the H-numbers. For this problem we pretend that these are the only numbers. The H-numbers are closed under multiplication.

As with regular integers, we partition the H-numbers into units, H-primes, and H-composites. 1 is the only unit. An H-number h is H-prime if it is not the unit, and is the product of two H-numbers in only one way: 1 × h. The rest of the numbers are H-composite.

For examples, the first few H-composites are: 5 × 5 = 25, 5 × 9 = 45, 5 × 13 = 65, 9 × 9 = 81, 5 × 17 = 85.

Your task is to count the number of H-semi-primes. An H-semi-prime is an H-number which is the product of exactly two H-primes. The two H-primes may be equal or different. In the example above, all five numbers are H-semi-primes. 125 = 5 × 5 × 5 is not an H-semi-prime, because it's the product of three H-primes.

Input

Each line of input contains an H-number ≤ 1,000,001. The last line of input contains 0 and this line should not be processed.

Output

For each inputted H-number h, print a line stating h and the number of H-semi-primes between 1 and h inclusive, separated by one space in the format shown in the sample.

Sample Input

21 
85
789
0

Sample Output

21 0
85 5
789 62

思路:打表求出H-prime,再两两相乘,用树状数组优化求和问题即可
typedef long long LL;
typedef pair<LL, LL> PLL;

const int maxm = 1e6+5;

bool prime[maxm]; 
int vis[maxm];
int jud[maxm], siz = 0, C[maxm];

void add(int x, int val) {
    for(; x < maxm; x += lowbit(x))
        C[x] += val;
}

LL getsum(int x) {
    LL ret = 0;
    for(; x; x -= lowbit(x))
        ret += C[x];
    return ret;
}

void getHprime() {
    for(int i = 5; i < maxm; i += 4) {
        if(!prime[i]) {
            for(int j = 2*i; j < maxm; j += i)
                prime[j] = true;
            jud[siz++] = i;
            for(int k = 0; k < siz; ++k) {
                if(maxm / i >= jud[k]) {
                    if(!vis[jud[k] * i]++)
                        add(i*jud[k], 1);
                } else
                    break;
            }
            
        }
    }
    
}


int main() {
    getHprime();
    int n;
    while(scanf("%d", &n) && n) {
        printf("%d %lld\n", n, getsum(n));
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/GRedComeT/p/12222445.html