HDU 4548 素数打表 + 线段树

传送门:HDU 4548

题解

因为数据量和查询次数较大, 所以要用线段树求解
同时要注意美素数打表, 方法是对每个素数判断是否为美素数, 因为一个数字必定大于等于其各位数字之和,找到素数后它的各位数字之和是否为素数是已知的, 所以判断时比较容易


实现

  1. 美素数打表(下附素数打表模板)
  2. 建树
  3. 查询
//打出1 ~ n 之间的素数用数组p[]保存;(n >= 2)

void get_prime(){   
    int cnt = 1;//保存素数个数
    p[1] = 2;

    for (int i = 3; i < 1e6; i += 2) {
        int flag = 0;
        for (int j = 1; j <= cnt && p[j] * p[j] <= i; ++j) {
            if (i % p[j] == 0) {
                flag = 1;
                break;
            }
        }

        if (!flag)  p[++cnt] = i;
    }
}       

AC code:

/*
 * Author : adrui
 * Language : C++
 * Result : Accepted
 * Love : yy
 * Favorite : Dragon Balls

 * Standing in the Hall of Fame
*/


#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

#define debug 0
#define LL long long
#define inf 0x7f7f7f7f
#define mod 10003
#define mid ((l + r) >> 1)
#define ls rt << 1, l, mid
#define rs rt << 1|1, mid + 1, r
#define M(a, b) memset(a, b, sizeof(a))

const int maxn(1e6 + 5);

int f[maxn], prime[maxn], p[maxn], sum[maxn << 2];

int getsum(int x) {
    int res = 0;

    while (x) {
        res += x % 10;
        x /= 10;
    }

    return res;
}

void init() {
    //getsum();
    M(prime, 0);
    M(f, 0);
    f[2] = prime[2] = 1;                                    //2
    p[1] = 2;

    int cnt = 1;
    for (int i = 3; i < 1e6; i += 2) {
        int flag = 0;
        for (int j = 1; j <= cnt && p[j] * p[j] <= i; ++j) {
            if (i % p[j] == 0) {
                flag = 1;
                break;
            }
        }

        if (!flag) {
            p[++cnt] = i;
            prime[i] = 1;
            if (prime[getsum(i)]) {
                f[i] = 1;
            }
        }
    }

}

void pushUp(int rt) {
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void build(int rt, int l, int r) {
    if (l == r) {
        sum[rt] = f[l];
        return;
    }

    build(ls);
    build(rs);
    pushUp(rt);
}

int query(int rt, int l, int r, int ql, int qr) {
    if (ql <= l && qr >= r)
        return sum[rt];

    int res = 0;
    if (ql <= mid)  res += query(ls, ql, qr);
    if (qr > mid)   res += query(rs, ql, qr);

    return res;
}

int main() {
#if debug
    freopen("in.txt", "r", stdin);
#endif //debug

    cin.tie(0);
    cin.sync_with_stdio(false);

    init();
    build(1, 1, 1e6);

    int T, l, r, kase = 0;
    cin >> T;

    while (T--) {
        cout << "Case #" << ++kase << ": ";
        cin >> l >> r;
        cout << query(1, 1, 1e6, l, r) << endl;
    }

    return 0;
}


go on

博客一段没更了, 近期会补上之前的进度

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值