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; }