题意:首先定义了一种叫做Reverse Prime的数:是一个7位数,倒置后是一个<=10^6的素数
然后要把所有的Reverse Prime求出来,排好序。
然后题目有2种操作:
q x :求编号0到编号x的Reverse Prime的质因数个数的和
然后要把所有的Reverse Prime求出来,排好序。
然后题目有2种操作:
q x :求编号0到编号x的Reverse Prime的质因数个数的和
d x :从表中删掉x(x是一个Reverse Prime)
思路:首先筛选出所有的素数,然后倒置,因为我们的素数都是<=10^6的,所以我们一定互有2,5这两个因子,还有的是:这道题也应用 的树状数组选出序列第k小的数的方法,用到了两个树状数组
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int MAXN = 1000005;
int vis[MAXN],prime[MAXN],cnt;
int fac[MAXN],a[MAXN],tot,p[MAXN];
long long s1[MAXN],s2[MAXN];
map<int, int> m;
int lowbit(int x){
return x&(-x);
}
void update(long long *s, int x, int val){
while (x <= cnt){
s[x] += val;
x += lowbit(x);
}
}
long long sum(long long *s, int x){
long long ret = 0;
while (x > 0){
ret += s[x];
x -= lowbit(x);
}
return ret;
}
int solve(int num){
int n = 0,ret = 0,bit[20];
while (num){
bit[n++] = num%10;
num /= 10;
}
for (int i = 0; i < n; i++)
ret = ret*10+bit[i];
while (ret < 100000)
ret *= 10;
return ret;
}
void init(){
memset(vis, 0, sizeof(vis));
for (int i = 2; i < MAXN; i++)
if (!vis[i]){
prime[++cnt] = i;
for (int j = 1; j*i < MAXN; j++)
vis[i*j] = 1;
}
for (int i = 1; i <= cnt; i++)
a[i] = solve(prime[i]);
sort(a+1, a+1+cnt);
for (int i = 1; i <= cnt; i++)
m[a[i]] = i;
for (int i = 1; i <= cnt; i++){
fac[i] = 2;
int tmp = a[i];
for (int j = 1; j<=cnt&&prime[j]*prime[j]<=tmp; j++)
while (tmp%prime[j] == 0){
tmp /= prime[j];
fac[i]++;
}
if (tmp > 1)
fac[i]++;
}
}
int main(){
char ch[5];
int k;
init();
memset(s1, 0, sizeof(s1));
memset(s2, 0, sizeof(s2));
for (int i = 1; i <= cnt; i++)
update(s1, i, 1);
for (int i = 1; i <= cnt; i++)
update(s2, i, fac[i]);
while (scanf("%s%d", ch, &k) != EOF){
if (ch[0] == 'd'){
int pos = m[k/10];
update(s1, pos, -1);
update(s2, pos, -fac[pos]);
}
else {
k++;
int l = 1, r = cnt,mid;
while (l <= r){
mid = (l+r)>>1;
long long tmp = sum(s1, mid);
if (tmp == k)
break;
if (tmp < k)
l = mid+1;
else r = mid-1;
}
printf("%lld\n", sum(s2, mid));
}
}
return 0;
}