UVa11610 - Reverse Prime
题目大意
定义了一种叫做Reverse Prime的数:位数为7位,倒转之后是六位的素数
要求按顺序找出所有的Reverse Prime,并计算出每个Reverse Prime的因子数
可以对这些数进行一下两种操作:
1、“q i”查询区间[0,i]Reverse Prime的因子数之和
2、“d reverse_prime”把reverse_prime这个Reverse Prime从序列中删除
题解
先把所有的Reverse Prime求出来,我们可以用筛选法求出所以六位的素数,然后进行倒置,然后在末位加一个0,这样就是Reverse Prime了,之后求出每个Reverse Prime的因子数,并对这些Reverse Prime进行升序排序,最后对这些数进行离散化。我们用两个树状数组来进行维护,一个树状数组用来记录位置0到位置i有多少个Reverse Prime,另外一个树状数组用来维护因子数和。对于第一个操作,用二分查找当前序列第i个Reverse Prime的位置,然后求因子数的前缀和,对于第二个操作,由于对Reverse Prime进行离散化了,可以直接找到这个Reverse Prime所在的位置,然后把这个位置上的Reverse Prime值置为0即可,非常好的题,挺综合的
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define MAXN 1000000 using namespace std; typedef struct { int b; int pr; } NODE; NODE s[MAXN+5]; int a[MAXN+5],q1[MAXN+5],q2[MAXN+5],f[MAXN+5]; int ans; int id[MAXN*10+5]; 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<=MAXN; i++) if(!f[i]) { a[++ans]=i; for(j=i*i; j<=MAXN; 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<1000000) 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(void) { //freopen("prime.txt","r",stdin); //freopen("prime.out","w",stdout); 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; }