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;
}

posted on 2013-05-02 13:49  仗剑奔走天涯  阅读(219)  评论(0编辑  收藏  举报

导航