http://acm.hdu.edu.cn/showproblem.php?pid=5812
题意很明确,首先要知道
d(a,b)=f(a/gcd(a,b))+f(b/gcd(a,b))
,这个f(x)表示x由几个素因子构成,可以预处理出来100W以内的所有f,用线性筛。
然后对于每次Q操作的x,可以枚举它的gcd y,然后去集合里找y的倍数z,使得f(z/y)=s最小。首先枚举每个数的因子是sqrt(x)的复杂度,所以每次加入集合的时候,可以把所有数字的因子都给枚举了,复杂度是
O(q∗sqrt(x))
,然后我们发现f最大,不超过20,所以我们可以开个数组C[y][s]表示y的倍数并且f(z/y)=s的出现的个数,然后在加入集合枚举的时候++,删除的时候–,然后查询的时候就直接枚举gcd,然后0-20枚举,复杂度是
O(q∗sqrt(x)∗20)
,能过
注意每个元素只能加入一次
代码:
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 200005
#define MAXN 1000005
#define maxnode 205
#define sigma_size 26
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-4;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
bool prime[1000005];
int pr[1000005];
int f[1000005];
int c[1000005][20];
int tot;
set<int> se;
void init(){
mem(prime,0);
mem(c,0);
tot=0;
f[1]=0;
for(int i=2;i<=1000000;i++){
if(!prime[i]){
pr[tot++]=i;
f[i]=1;
}
for(int j=0;j<tot&&pr[j]*i<=1000000;j++){
prime[pr[j]*i]=1;
f[pr[j]*i]=f[i]+1;
if(i%pr[j]==0){
break;
}
}
}
}
void add(int a,int d){
int m=sqrt(a);
for(int i=1;i<=m;i++){
if(a%i==0){
if(i==a/i){
c[i][f[a/i]]+=d;
}
else{
c[i][f[a/i]]+=d;
c[a/i][f[i]]+=d;
}
}
}
}
int main(){
//freopen("in.txt","r",stdin);
int q,kase=0;
init();
while(cin>>q&&q){
kase++;
printf("Case #%d:\n",kase);
se.clear();
while(q--){
char s[10];
int a;
scanf("%s%d",s,&a);
if(s[0]=='I'){
if(!se.count(a)) add(a,1),se.insert(a);
}
else if(s[0]=='D'){
if(se.count(a)) add(a,-1),se.erase(a);
}
else{
if(se.empty()){
printf("-1\n");
continue;
}
int m=sqrt(a);
int ans=INF;
for(int i=1;i<=m;i++){
if(a%i==0){
for(int j=0;j<20;j++){
if(c[i][j]){
ans=min(ans,f[a/i]+j);
//break;
}
if(c[a/i][j]){
ans=min(ans,f[i]+j);
//break;
}
}
}
}
printf("%d\n",ans);
}
}
for(set<int>::iterator it=se.begin();it!=se.end();it++){
add(*it,-1);
}
}
return 0;
}