Description
There are a few 7 digit positive numbers whose reverse number is a prime number and less than 10^6. For example: 1000070, 1000090 and 1000240 are first few reverse prime numbers because all of the numbers are 7 digit numbers whose reverse number is a prime number and less than 10^6. You have to find out all the 7 digit reverse prime numbers and also its number of prime factors. Prime factors of a positive integer are the prime numbers that divide into that integer exactly, without leaving a remainder. For example, prime factors of 24 are 2, 2, 2 and 3.
In this problem, youll encounter 2 types of input
Query:
This type of input will be formatted like this q i. For this input, you have to calculate the cumulative summation of the number of prime factors of reverse prime numbers from 0-th to i-th index.
Deletion:
This type of input will be formatted like this d reverse_prime. For this input, you have to delete reverse_prime from the set and update your summation. No output is required in such cases.
It is guaranteed that i will be a valid index and reverse_prime will be a valid 7 digit reverse prime number. It is also guaranteed that no two reverse_prime will be same.
There will be at most 71000 query lines and 3500 deletion lines in the data set. The program will terminated by EOF.
题目大意
定义了一种叫做Reverse Prime的数:
位数为7位,倒转之后是六位的素数
要求按顺序找出所有的Reverse Prime,并计算出每个Reverse Prime的因子数
可以对这些数进行一下两种操作:
1、“q i”查询区间[0,i]Reverse Prime的因子数之和
2、“d reverse_prime”把reverse_prime这个Reverse Prime从序列中删除
Part 1
对于每个Reverse Prime,我们可以按照定义, Reverse Prime的倒序是一个六位数,而Reverse Prime本身是一个七位数,那么我们可以知道Reverse Prime的最后一位一定是0;
那么对于每一个Reverse Prime,求出所有的六位的素数,将其倒序的末尾加上一个0就是Reverse Prime了
求素数是可以使用埃拉托斯特尼筛法
然后。。。打表出奇迹打出素数表
Part 2
对于每个处理好的Reverse Prime,我们求出它的的因数。然后依照题意排序。
对于求第几个Reverse Prime我们建立一个树状数组用来记录位置0到位置i有多少个Reverse Prime
对于第一个操作,用二分查找当前序列第i个Reverse Prime的位置.
这里就需要求区间第k大的数,可以用树状数组来解决。:建一个权值树状数组。求第k大的数,不就是求getsum[1,val]≈k的数。
然后求因子数的前缀和。
然而暴力枚举依然会超出时间上线。
但是。我们要求的是前缀和—
于是我们可以建立第二个树状数组来记录因数!
对于第二个操作:
给定了Reverse Prime的值
但是仍然不方便找到Reverse Prime
由于对Reverse Prime进行离散化了,可以直接找到这个Reverse Prime所在的位置。
然后把这个位置上的Reverse Prime值置为0即可,同时也将第一个树状数组的个数-1。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
struct NODE
{
int b;
int pr;
} ;
NODE s[1000005];
int a[1000005],q1[1000005],q2[1000005],f[1000005],ans,id[1000005];
int lowbit(int x)
{
return x&-x;
}
int sum(int *c,int x)
{
int ret=0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
void add(int *c,int x,int d)
{
while(x<=ans)
{
c[x]+=d;
x+=lowbit(x);
}
}
void prime()
{
long long i,j;
ans=0;
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
for(i=2; i<=100000; i++)
if(!f[i])
{
a[++ans]=i;
for(j=i*i; j<=100000; j+=i)
if(!f[j]) f[j]=i;
}
}
void fac(int i,int sum)
{
while(sum%2==0)
{
s[i].pr++;
sum/=2;
}
while(f[sum])
{
s[i].pr++;
sum/=f[sum];
}
if(sum!=1) s[i].pr++;
}
void deal(int x,int p)
{
int sum=0;
while(x)
{
sum=sum*10+x%10;
x/=10;
}
while(sum<100000)
sum*=10;
s[p].pr=2;
fac(p,sum/10);
s[p].b=sum;
}
void solve()
{
int i;
for(i=1; i<=ans; i++)
deal(a[i],i);
}
bool cmp(NODE x,NODE y)
{
return x.b<y.b;
}
int main()
{
char ch[5];
int i,t,l,r,m;
memset(s,0,sizeof(s));
memset(q1,0,sizeof(q1));
memset(q2,0,sizeof(q2));
prime();
solve();
sort(s+1,s+ans+1,cmp);
for(i=1; i<=ans; i++)
add(q2,i,s[i].pr);
for(i=1; i<=ans; i++)
{
id[s[i].b]=i;
add(q1,i,1);
}
while(scanf("%s",ch)!=EOF)
{
scanf("%d",&i);
if(ch[0]=='q')
{
++i;
l=1;
r=ans;
while(l<=r)
{
m=(l+r)>>1;
t=sum(q1,m);
if(t==i) break;
if(t>i)
r=m-1;
else
l=m+1;
}
printf("%d\n",sum(q2,m));
}
else
{
t=id[i];
add(q1,t,-1);
add(q2,t,-s[t].pr);
}
}
return 0;
}