您的位置:首页 > 编程语言 > C语言/C++

HDU 4548 素数打表 + 线段树

2016-11-02 16:11 323 查看
传送门:HDU 4548

题解

因为数据量和查询次数较大, 所以要用线段树求解

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

实现

美素数打表(下附素数打表模板)

建树

查询

//打出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

博客一段没更了, 近期会补上之前的进度
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ ACM HDU 线段树 素数