HDU 5812 Distance

题意是,一堆操作,I是添加一个数,D是去掉一个数,Q是询问这个数如果通过乘除质数,x次能到集合中任何一个数,问最少次数。

NUM是每个数的质因子个数,通过筛法筛出来;这里规定乘一个质数称之为一次,Ci,j是指i这个数,j次能到达集合中的数的数量。ans中是一个二进制数,表示这个可以几次到(相应位置是1),当让也可以直接用c数组去遍历,这样不是看着清楚么

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <set>

using namespace std;
const int INF = 0x7f7f7f7f;
const int MAXN = 1e6 + 11;

int num[MAXN];
int c[MAXN][21];
int ans[MAXN];

void init()
{
    num[1] = 0;
    for (int i = 2; i < MAXN; ++i)
    {
        if (!num[i])
        {
            num[i] = 1;
            for (int j = i + i; j < MAXN; j += i)
            {
                int temp = j;
                while (temp % i == 0)
                {
                    ++num[j];
                    temp /= i;
                }
            }
        }
    }
}
set<int>st;
set<int>::iterator iter;
int main()
{
    init();
    int T,p,ncas=1;
    char s[5];
    while (scanf ("%d",&T)&&T)
    {
        st.clear();
        memset(c,0,sizeof(c));
        memset(ans,0,sizeof(ans));
        printf ("Case #%d:\n",ncas++);
        while (T--)
        {
            scanf ("%s%d",s,&p);
            if (s[0]=='I')
            {
                if ( (iter = st.find(p)) != st.end() )continue;
                else st.insert(p);
                for (int i=1; i*i<=p; i++)
                {
                    if (p%i==0)
                    {
                        int a=i,b=p/i;
                        c[a][num[b]]++;
                        if (c[a][num[b]]==1) ans[a]+=(1<<num[b]);
                        c[b][num[a]]++;
                        if (c[b][num[a]]==1) ans[b]+=(1<<num[a]);
                    }
                }
            }
            else if (s[0]=='D')
            {
                if ( (iter = st.find(p)) == st.end() )continue;
                else st.erase(p);
                for (int i=1; i*i<=p; i++)
                {
                    if (p%i==0)
                    {
                        int a=i,b=p/i;
                        c[a][num[b]]--;
                        if (c[a][num[b]]==0) ans[a]-=(1<<num[b]);
                        c[b][num[a]]--;
                        if (c[b][num[a]]==0) ans[b]-=(1<<num[a]);
                    }
                }
            }
            else
            {
                int out=0x7f7f7f7f;
                if (st.size())
                {
                    for (int i=1; i*i<=p; i++)
                    {
                        if (p%i==0)
                        {
                            int j,a=i,b=p/i;
                            for (j=0; j<22; j++)
                            {
                                if (ans[a]&(1<<j)) break;
                            }
                            if (j!=22) out=min(out,j+num[b]);

                            for (j=0; j<22; j++)
                            {
                                if (ans[b]&(1<<j)) break;
                            }
                            if (j!=22) out=min(out,j+num[a]);
                        }
                    }
                }
                if (out==0x7f7f7f7f) printf ("-1\n");
                else printf ("%d\n",out);
            }
        }
    }
    return 0;
}

 

posted on 2016-08-12 14:56  very_czy  阅读(156)  评论(0编辑  收藏  举报

导航