poj-3292

26 篇文章 0 订阅
//5248K 16MS    G++
#include <stdio.h>
#include <string.h>

const int MAX = 1000010;

char HPNumber[MAX];
int HSPNumber[MAX];

void table() {

    memset(HPNumber, 0 ,sizeof(HPNumber));
    memset(HPNumber, 0 ,sizeof(HSPNumber));
    // at begin, all H-number are h-prime

    for (int i = 5; i <= MAX; i = i+4) {
        for (int j = 5; j <= MAX; j = j+4) {

            int multiply = i*j;
            if (multiply > MAX) {
                break;
            }

            // i and j are all h-prime, semi-h-prime
            if (!HPNumber[i] && !HPNumber[j]) {
                HPNumber[multiply] = -1;
            } else { // i and j all not all semi-h-prime
                HPNumber[multiply] = -2; // not semi-h-prime
            }
        }
    }

    int curHSPNum = 0;
    for (int i = 1; i <= MAX; i ++) {
        if (HPNumber[i] == -1) { // counter a h-semi-prime
            curHSPNum++;
        }
        HSPNumber[i] = curHSPNum;
    }
}

int N;
int main() {
    table();
    while(scanf("%d", &N) != EOF) {
        if (!N) {
            return 0;
        }
        printf("%d %d\n", N, HSPNumber[N]);
    }
}

从解法上看算是个水题,就是纯遍历进行筛选,然后统计一下N之前有多少个H-semi-prime,

不过还是有重要思路的,首先,如何确定一个H-prime? 我最开始还向着是不是先搞一遍素数筛子,然后,再结合H-number来得到 H-prime,

后来,看了别人的题解,才发觉自己是想多了,完全可以假设一开始所有的h-number都是h-prime, 然后再从小到大的进行乘积筛选,逐渐去掉非h-prime,

同时根据乘积来判断 h-semi-number 和 非h-semi-number,

流程就是:

两重循环h-number,都是从5开始(最小的非1 h-number)这一点很关键,保证了算法的正确性,分别用i, j表示,

而 i * j 也必定是h-numner((4*A + 1)*(4*B + 1) 最后也可以表示为 4*C + 1 的形式), 如果 i 和 j 都是 h-prime, 那么 i*j 就是 h-semi-prime,在HP[]数组中将i 和 j置为 -1(初始为0,表示为h-prime)

而如果i 和 j 不全是h-prime, 那么i * j必定不是 h-semi-prime,因为必然可以表示为3个或以上的h-prime相乘, 置为-2(为何和 h-semi-prime 和 h-prime区分开)

最后遍历整个HP[]数组,统计一下每个数前面出现了多少个h-semi-prime即可。


这个题的思路本质上和素数筛子差不多,是不过多了一种标示罢了,都是先假设全部的数都是满足条件的,然后从小到大,一一排除.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值