牛客练习赛25 a-贝利福斯数(素数筛法的应用)

题目链接

题意: 定义ax+1 为新的数,如果ax+1 不能分解成两个ay+1之积,那么称为素数!
求[1,n] 里的能分解成两个ax+1素数之积的数的个数。


很毒奶的题目!首先数据非常大!而且有坑点!
先说说性质吧!
(ax + 1) * (ay + 1) = a[ axy + x + y ] + 1 仍然为一个ax+1 数!
很明显我们可以仅对x、y分析,就变成连续区间[1,(n-1)/a] 内数分析!
如果数k 能表示成 k= axy + x + y,那么k(ak+1) 就不是素数!
线性筛法很快将其全部素数搞出!坑点来了!
数k = (ax + 1) (ay + 1) = (am + 1)(an + 1) ,且 (ax+1) 、(ay+1) 、(am+1)、(an+1)均为素数,那么就不能直接枚举两个素数之积不超过n的对数,有重复!
4641 = 51*91 = 21*221 ,如果你枚举计数,对不起gg了!

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#define llt long long
#include <map>
#define fi first
#define se second
#define lson (rt<<1)
#define rson ((rt<<1)+1)
using namespace std;

const int N =2*1e7+77;
int Prim[N];
bool is[N]={false};
bool boo[N]={false};
int main(){
   // freopen("out1.txt","w",stdout);
    int a,n;
    scanf("%d%d",&a,&n);
    int d = (n-1)/a;

    int cnt = 0;
    int ans = 0;

    for(int i=1;i<=d;++i){
        if(is[i]) continue;
        Prim[cnt++] = i;
        llt t = a*i+1;
        for(llt j = 1ll*a*i*i+2*i;j<=d;j = j+t)
            is[j] = true;
    }
    //直接枚举两个素数之积不超过n的对数,计算重复了!
//    for(int i=0;i<cnt;++i)
//    {
//        int k = (d - Prim[i])/(a*Prim[i]+1);
//        //cout<<k<<endl;
//        ans = ans + (upper_bound(Prim+i,Prim+cnt,k)-Prim-i);
//
//    }
//    printf("%d\n",ans);
    memset(boo,0,sizeof(boo));
    for (int q=0;q<cnt;q++)
    {
        int i=Prim[q];
        for (int k=0;k<cnt;k++)
        {
            llt j=Prim[k];
            if ((a*i*j+i+j)>d) break;
            boo[a*i*j+i+j]=1;
        }
    }

    for (int i=1;i<=d;i++)
    if (boo[i]) ans++;

    cout<<ans<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值