题目链接:点击打开链接
解题思路:dis(x,y) == g(x/gcd(x,y)) + g(y/gcd(x,y)),g(x)就是x最多分解出多少个质数的乘积数,那么我们枚举x个约数个数,然后在集合中找出一个数y使得它是这个约数的倍数,且g(y)尽量小,这个用一个multiset就可以解决问题了。
#include<bits/stdc++.h>
using namespace std;
const int mx = 1e6+10;
typedef long long ll;
int n,m;
int pri[mx],top,cnt[mx];
bool vis[mx];
set <int> se;
multiset <int> st[mx];
void init()
{
top = 0,cnt[1] = 0,cnt[0] = 1e9;
for(int i=2;i<mx;i++){
if(!vis[i]) pri[top++] = i,cnt[i] = 1;
for(int j=0;j<top&&pri[j]*i<mx;j++){
vis[pri[j]*i] = 1;
cnt[pri[j]*i] = cnt[i]+1;
if(i%pri[j]==0) break;
}
}
}
int main()
{
char c[10];
init();
int sq,a,cas = 1;
while(~scanf("%d",&n)&&n){
//memset(val,0,sizeof(val));
for(int i=1;i<mx;i++) st[i].clear();
se.clear();
printf("Case #%d:\n",cas++);
while(n--){
scanf("%s%d",c,&a);
if(c[0]=='I'){
if(se.count(a)) continue;
int i;
for(i=1;i*i<a;i++){
if(a%i) continue;
st[i].insert(cnt[a/i]);
st[a/i].insert(cnt[i]);
}
if(i*i==a) st[i].insert(cnt[i]);
se.insert(a);
}else if(c[0]=='D'){
if(!se.count(a)) continue;
int i;
for(i=1;i*i<a;i++){
if(a%i) continue;
st[i].erase(st[i].lower_bound(cnt[a/i]));
st[a/i].erase(st[a/i].lower_bound(cnt[i]));
}
if(i*i==a) st[i].erase(st[i].lower_bound(cnt[i]));
se.erase(a);
}else{
int ans = 1e9;
for(int i=1;i*i<=a;i++){
if(a%i) continue;
if(!st[i].empty()) ans = min(ans,cnt[a/i]+(*st[i].begin()));
if(!st[a/i].empty()) ans = min(ans,cnt[i]+(*st[a/i].begin()));
}
printf("%d\n",ans==1e9?-1:ans);
}
}
}
return 0;
}