洛谷 P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib

传送门

看到题解里边都是些什么鬼东西,然后我就来发着篇题解了,都是些什么群魔乱舞

首先这个题我用的欧拉筛做的,然后欧拉筛是什么:
\(\omicron\)(n) 的时间复杂度内筛出质数与积性函数的优秀算法
每一个合数都被它的最小质因子筛掉.
对于每一个i,从小到大枚举当前得到的所有质数p,那么$p \times i $ 一定不是质数(显然),然后枚举到\(p | i\) 为止。
我们假设n的最小质因子是q,那么当 i = $\frac{a}{b} $ , p = q时,n才会被筛掉(显然).
这样每一个数之会被筛掉一次,所以时间复杂度是\(\omicron\)(n)的.
code:
void shai(int s) {
    b[1] = 1;
    for (int i = 2; i <= s; i++) {
        if (!b[i]) prime[++num] = i;
        for (int j = 1; j <= num; j++) {
            if (prime[j] * i >= s) break;
            b[prime[j] * i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}
那么这个题应该怎么用欧拉筛来做呢?

因为我们如果每次都判断一个数是不是质数,那么欧拉筛筛出来之后判断就成了\(\omicron\)(n)的,所以我是先把素数都筛出来,然后判断就行了啊...QwQ

因为最后一个点是\(n = 8\)的,很明显过不了啊,咋办???

希望大家心里永远都存在一句话:打表出省一!

我们就先把$ n = 8 \(时的解求出来就行了啊,反正\) n = 8 $的时候解也不多

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <vector>

#define N 100010
#define M 1010

using namespace std;
int prime[1000010];
int n, num;
bool b[10000010];

int read() {
    int s = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

void shai(int s) {
    b[1] = 1;
    for (int i = 2; i <= s; i++) {
        if (!b[i]) prime[++num] = i;
        for (int j = 1; j <= num; j++) {
            if (prime[j] * i >= s) break;
            b[prime[j] * i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

bool pd(int x) {
    for (int i = 1; i <= n; i++) {
        if (b[x] == 1) return 0;
        x = x / 10;
    }
    return 1;
}

int main() {
    n = read();
    if (n == 8) {
        puts("23399339");
        puts("29399999");
        puts("37337999");
        puts("59393339");
        puts("73939133");
        return 0;
    }
    int m = 1;
    for (int i = 1; i <= n; i++) m *= 10;
    shai(m);
    for (int i = m / 10; i < m; i++) {
        if (pd(i) == 1) printf("%d\n", i);
    }
    return 0;
}

转载于:https://www.cnblogs.com/zzz-hhh/p/11283341.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值