找数

题意

找出第N个最小素因子是P的正整数。
若结果超过 109(Maxn) 输出0。
1N,P109
TimeLimits:1000ms
MemoryLimits:64M

分析

我们很容易想到筛法,因为它能得出每个数的最小质因子。但是 N,P 都很大,只用筛法时间空间必然无法承受。我们考虑将P分类讨论。
假设 Ans=PK
我们可以设一个分界 X
P>X时,我们可以用筛法,知道 1 ~ MaxnP范围内的数最小质因子是什么,然后找到答案。
PX 时,我们可以二分搜索K,然后用容斥判断该范围内最小质因子大于等于 P 的数的个数是否有N个(即用总个数减去最小质因子小于 P 的数的个数)。
所以我们要找到一个合适的X使得在第一种情况下,它筛法不会超时或爆空间;在第二种情况下,比它小的质数数量不会太多。 X=70 或许不错。

#include <cstdio>
#include <algorithm>

const int N = 15000010,M = 1e6;
int n,P,tot,cnt,K;
int s[N],prime[M];

void work() {
    for (int i = 2;i < N;i ++) {
        if (!s[i]) prime[++ tot] = i,s[i] = i;
        for (int j = 1;j <= tot && prime[j] * i < N;j ++) {
            s[prime[j] * i] = prime[j];
            if (i % prime[j] == 0) break;
        }
    }
}

int calc(int lim) {
    int re = 0;
    for (int i = 0;i < K;i ++) {
        long long cur = 1;
        int nt = 0;
        for (int S = i,j = 1;S;S >>= 1,j ++) {
            if (S & 1) cur *= prime[j],nt ++;
        }
        if (nt & 1) re -= lim / cur;
        else re += lim / cur;
    }
    return re;
}

int main() {
    scanf("%d%d",&n,&P);
    work();
    if (P > 70) {
        int Max = 1e9,r = Max / P,i;
        n --;
        i = 1;
        for (;i <= r && n;i ++) if (s[i] >= P) {
            n --;
            if (!n) break;
        }
        if (!n) printf("%d\n",i * P);else printf("0");
    }
    else {
        for (tot = 0;prime[tot + 1] < P; ++ tot);
        int l = 0, r = 1e9 / P, ans = 0;
        K = 1 << tot;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (calc(mid) >= n) ans = mid, r = mid - 1; 
            else l = mid + 1;
        }
        printf("%d\n",ans * P);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值