传送门: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
博客一段没更了, 近期会补上之前的进度