poj 3292(筛法+两两组合)

Semi-prime H-numbers
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 6924 Accepted: 2959

Description

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

Source


题目比较简单,但却WA了好多次。
首先是对于H-prime的理解。首先H-prime必须是H-number(也就是模除4等于1),这个条件如果不满足的话,就无从谈起。
另外是与普通质数的对比。首先如果一个H-number同时也是质数,那它一定也是H-prime。比如5、13、17这样的数字。
反而,当一个H-number是合数, 那它也有可能是H-prime: 比如9。 这是因为他们无法拆分为两个H-number的乘积(3并不是H-number)。
因此判断H-number的方法就是: 能被4整除无法拆分为 2个H-number的乘积!

当找到了所有的H-prime,那么两两组合相乘,也就可以打表打出来MAXN以内的所有H-semi-primes来。这里不用担心MAXN*MAXN会tle,因为你设定好循环终止条件后,循环的效率会非常高,接近O(MAXN)。

提交记录:
1、WA 因为判断素数的时候条件写错,写成了遍历所有H-prime来判断能否找到两个H-prime的乘积等于num。其实这里并不要求 因子是H-prime,只要 是H-number就可以。
2、WA。主循环里 输入为0的时候需要跳出

AC代码:
/*Source Code

Problem: 3292		User: 775700879
Memory: 18060K		Time: 79MS
Language: G++		Result: Accepted
Source Code*/
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
               #define MAXN 1000100 #define oo 0x3f3f3f3f #define UPPER 2147483647 using namespace std; char A[200]; int bound; long long flag[MAXN] = {0}; long long prime[MAXN] = {0}; bool semi[MAXN] = {0}; long long semisum[MAXN] = {0}; int primenum = 0; void getprime() {//筛法求素数,得到的flag是标志数组,而prime是从2开始的素数链 long long i, j; memset(flag, false, sizeof(flag)); for (i = 5; i < MAXN; i+=4) flag[i] = true;//先让所有H-num都标注为true for(i = 5; i < MAXN; i+=4) { if (flag[i]) { for (j = 5; i*j < MAXN; j+=4) { //看似是一个MAXN*MAXN的二重循环,而其实后面筛得很密,很少进入内层循环 flag[i*j] = false; } prime[primenum++] = i; } } } void getsemi() { long long i, j; memset(semi, 0, sizeof(semi)); for (i = 0; i < primenum; i++) { for (j = i; prime[i] * prime[j] < MAXN && j < primenum; j++) {//这里prime[i] * prime[j]可能会溢出! semi[prime[i] * prime[j]] = true; } } } int main() { int i, j; getprime(); getsemi(); for (i = 1; i < MAXN; i++) { semisum[i] = semisum[i-1] + semi[i]; } int n; while (cin >> n) { if (n == 0) break; cout << n << " " << semisum[n]<< endl; } return 0; }  
              
             
            
           
          
        
       
       
      
      
     
     
    
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值