HDU5812 Distance 构造,预处理

分析:怎么看都是超时,但是可以先筛一遍1e6以内的每个数的最小素数

        算出每个数由多少个素数组成,然后应用,c[1e6][20]

        就是题解的那一套,参照题解,比赛的时候没有想到好的办法筛一个数的因子,醉了

        然后赛后发现,预处理因子肯定超时,虽然是O(nlogn)的,但是n是1e6啊,常数太大

       而且单组操作只有5e4,所以暴力sqrt(x)即可

#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+1;
int c[N][21],tot,prime[80000],mn[N],cnt[N],q,kase;
bool check[N];
char op[5];
void getprime()
{
    for(int i=2; i<=N-1; ++i)
    {
        if(!check[i])mn[i]=prime[++tot]=i;
        for(int j=1; j<=tot; ++j)
        {
            if(i*prime[j]>N-1)break;
            check[i*prime[j]]=true;
            mn[i*prime[j]]=prime[j];
            if(i%prime[j]==0)break;
        }
    }
}
void getcnt()
{
    for(int i=2; i<=N-1; ++i)
    {
        int tmp=i;
        while(tmp!=1)++cnt[i],tmp/=mn[tmp];
    }
}
int main()
{
    getprime();
    getcnt();
    memset(mn,0,sizeof(mn));
    while(~scanf("%d",&q),q)
    {
        printf("Case #%d:\n",++kase);
        memset(c,0,sizeof(c));
        int ttt=0;
        for(int i=0; i<q; ++i)
        {
            int x;
            scanf("%s%d",op,&x);
            if(op[0]=='I')
            {
                if(mn[x]==kase)continue;
                mn[x]=kase;++ttt;
                for(int j=1; j*j<=x; ++j)
                {
                    if(x%j)continue;
                    ++c[j][cnt[x/j]];
                    if(x/j!=j)++c[x/j][cnt[j]];
                }
            }
            else if(op[0]=='D')
            {
                if(mn[x]!=kase)continue;
                mn[x]=0;--ttt;
                for(int j=1; j*j<=x; ++j)
                {
                    if(x%j)continue;
                    --c[j][cnt[x/j]];
                    if(x/j!=j)--c[x/j][cnt[j]];
                }
            }
            else
            {
                if(ttt==0){printf("-1\n");continue;}
                int ans=100;
                for(int j=1; j*j<=x; ++j)
                {
                    if(x%j)continue;
                    for(int k=0; k<=20; ++k)
                    {
                        if(c[j][k])
                        {
                            ans=min(ans,k+cnt[x/j]);
                            break;
                        }
                    }
                    if(x/j!=j)
                    {
                        for(int k=0; k<=20; ++k)
                        {
                            if(c[x/j][k])
                            {
                                ans=min(ans,k+cnt[j]);
                                break;
                            }
                        }
                    }
                }
                if(ans==100)ans=-1;
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2016-08-10 11:10  shuguangzw  阅读(289)  评论(0编辑  收藏  举报