POJ3292 Semi-prime H-numbers

题意:定义一种新的数叫H数,它们是所有形如4k+1的整数,其中,k是非负整数。在这个题目中,只考虑H数而不考虑其他整数。同时定义了H质数和H合数,H质数即只能被1和本身整除(注意,这个时候的“只能”只局限在H数范围内),H合数即恰好可以分解为两个H质数的乘积。

现在给出一个H数h,问1到h中,有多少个H合数。


这个纯粹是把通常意义的整数的整除和质数、质因子的概念做了一个整体改变,放在4k+1型数下考虑,题目读明白了就可做了。

思路:首先预处理出所有的H数,找出1000000以内的就够了,不难想到实际规模是250000,在这个过程中同时判定每个H数是不是H质数,这个是因为我得到一个H数时,我肯定已经得到了比它小的H数,因此,一定可以判断现在这个H数是不是H质数。用一个m数组来标记,如果H数i为H质数,就标记m[i]=1,否则为0.

其次就是做第二张表了,这张表用一个一维数组table来实现,其中table[i] 是第i个H数及其之前有多少个H合数,具体步骤是:对每个H数,如果它是H质数,那么在它及以前的H合数的数目一定等于上一个H数及其之前的H合数数目,因为本身是质数嘛,不增加答案,即table[i]=table[i-1]   ,如果不是H质数的话就对其进行分解,看能否找到一个H质数(注意必须是H质数而不仅仅是H数)来整除它,且商依然是H质数(这样的话就代表这个数可以分解为两个H质数的乘积了),这样就得到了一个H合数,答案加一,并计入table[i]

当然还有种可能,这个H数并不是H质数,然而它却也不是H合数,这时要在后面再加一个判断(即代码中的check变量),这种情况出现了的话,就继承上一个H数的答案,即table[i]=table[i-1]

这就得到了答案表了,直接打表即可

code:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstdlib>


#define maxn 1001010
#define inf 0x3f3f3f3f
#define LL long long

using namespace std;

int m[1000100];
int table[250050]= {0};
void init()
{
    memset(m,0,sizeof(m));
    m[1]=m[5]=1;
    for(int i=2; 4*i+1<=1000005; i++)
    {
        int tmp=4*i+1;
        bool check=true;
        for(int j=1; j<i&&((4*j+1)*(4*j+1))<=tmp; j++)
        {
            int tp=4*j+1;
            if(tmp%tp==0)
            {
                int tpp=tmp/tp;
                if((tpp-1)%4==0)
                {
                    check=false;
                }
            }
        }
        if(check)m[tmp]=1;
    }
    return;
}
void init2()
{
    int n=1000001;
    int ans=0;
    int r=(n-1)/4;
    for(int i=1; i<=r; i++)
    {
        int tmp=4*i+1;
        bool check=true;
        if(m[tmp])
        {
            table[i]=table[i-1];
            continue;
        }
        for(int j=1; j<i; j++)
        {
            int tp=4*j+1;
            if(tp*tp>tmp)break;
            if(m[tp])//找到一个H质数
            {

                if(tmp%tp==0)//如果这个H质数能整除tmp
                {
                    if(m[tmp/tp])//且商还是个H质数,就得到H合数了
                    {
                        check=false;
                        ans++;
                        table[i]=ans;
                        break;
                    }
                }
            }
        }
        if(check)table[i]=table[i-1];//不是H质数却也不是H合数的情况,继承答案
    }
}
int main()
{
    int n;
    init();
    init2();
    while(scanf("%d",&n)&&n)
    {
        printf("%d %d\n",n,table[(n-1)/4]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值