这个题目很巧妙。其实刚开始是没有任何想法的,但是仔细分析一下套路就会发现。其实是正常的套路。
首相,这是个询问类型的题。给你定义了一个函数d( x , y ) 为从x 到 y要乘或除的素数的最小个数。但是不可以0(n^2)肯定会超时(普遍的套路) ;
但是这个题目要抓住一个特殊的点。因为这个是集合操作,包括了insert和delete, 可以在insert和delete的同时维护什么东西。这样的话query的时候可以直接使用这里面维护的东西。问题是维护什么
分析原式。可以知道d(x , y) = f(x / gcd) + f(y / gcd) ; 这样就自然想到枚举gcd , x约数。那么知道了约数g,前半部分也就知道了,这样就只有一个未知数。f(y / g) ; 但是y必须在S内。不可能枚举S内的东西。所以可以在insert的同时记录。自然想到、记录d[x] ,表示约数是x的时候,S内的最小值。更新只需要在insert时d[x] = min(d[x] , f(data / x)) ;
但是如果删除了data,怎么办。这样的话记录第二小,第三小。。。。最后等于维护一个链表,但是肯定是不行的。所以必须要换一个方法。考虑到一个关键点。每个数的素因子的个数小于20 ; 所以把20作为第二维。c[g][s] 表示g的约束,S中g的倍数data的f (data / g) = k 的个数 ; 因为题目中需要判断s是否存在一个data,如果存在就可以直接使用s代替f(y / gcd) ; 不需要确切的值,可以避免搜索,所以可以减少复杂度。这样。只需要维护C数组就可以做出口来了。
可以使用一些列的优化。但是注意query的时候,for(z=0;z<20;z++) 在判断是约束才进行,。这样可以搞出来 ,否者可能会TLE。 加上lowbit优化。就可以不用循环z那个20,但是要开一个数组维护个个bit位,因为s很小。。。也无所谓,如果S很大,那么就必须要优化。
代码900ms:,写的比较挫:
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#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 1000005
#define MAXN 2000005
#define maxnode 500010
#define sigma_size 30
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define mid int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem0(x) memset(x,0,sizeof(x))
#define mem1(x) memset(x,-1,sizeof(x))
#define meminf(x) memset(x,INF,sizeof(x))
#define lowbit(x) (x&-x)
#define S(n) scanf("%d",&n)
#define P(n) printf("%d ",n)
#define PN(n) printf("%d\n",n)
#define FP(k) freopen(k , "r" ,stdin)
#define RPTI(s , n) for(int i=s;i<n;i++)
#define RPTJ(s , n) for(int j=s;j<n;j++)
#define RPTK(s , n) for(int k=s;k<n;k++)
#define RPTL(s , n) for(int l=s;l<n;l++)
const LL mod = 1000000;
///const int prime = 999983;
const int INF = 0x3f3f3f3f;
const int INFF = 1e9;
const double pi = 3.141592653589793;
const double inf = 1e18;
const double eps = 1e-10;
inline int read_int(){
int ret=0;
char tmp;
while(!isdigit(tmp=getchar()));
do{
ret=(ret<<3)+(ret<<1)+tmp-'0';
}
while(isdigit(tmp=getchar()));
return ret;
}
/*******************************************/
typedef long long ll ;
const int moddd = 1e9 + 7 ;
int nums[1000005] ;
int prime[1000005] ;
int cntpri = 0 ;
int bin[1100005] ;
int bin2[1100005] ;
void init(){
mem0(nums) ;
mem0(bin) ;
for(int i=2;i<=1000000;i++){
if(nums[i] == 0){
nums[i] = 1 ;
prime[cntpri++] = i ;
}
for(int j=0;j<cntpri&&i*prime[j]<=1000000;j++){
nums[i*prime[j]] = nums[i] + 1 ;
if(!(i % prime[j])) break ;
}
}
int ci = 0 ;
for(int i=1;i<=1100000;i*=2 , ci ++){
bin[i] = ci , bin2[ci] = i ;
}
}
int c[1000005][25] ;
int d[1000005] ;
void update(int i , int j , int val){
if(c[i][j] == 0 && val == -1) d[i] = d[i] - bin2[j] ;
else if(c[i][j] == 1 && val == 1) d[i] = d[i] + bin2[j] ;
}
void add(int data , int val){
int s = sqrt(data) ;
for(int i=1;i<=s;i++)if(data % i == 0){
if(i * i == data){
c[i][nums[data/i]] += val ;
update(i , nums[data/i] , val) ;
}
else {
c[i][nums[data/i]] += val ;
update(i , nums[data/i] , val) ;
c[data/i][nums[i]] += val ;
update(data/i , nums[i] , val) ;
}
}
}
int main(){
init() ;
int n ;
int ca = 0 ;
set <int> s ;
while(scanf("%d" , &n)!=EOF){
if(n == 0) break ;
if(s.size() != 0){
set <int>::iterator si ;
for(si = s.begin() ; si != s.end() ; si ++){
int data = * si ;
add(data , -1) ;
}
s.clear() ;
}
mem0(d) ;
printf("Case #%d:\n" , ++ca) ;
char str[10] ;
int data ;
for(int i=0;i<n;i++){
scanf("%s" , str) ;
if(str[0] == 'I'){
scanf("%d" , &data) ;
if(s.count(data) == 1) continue ;
else {
s.insert(data) ;
add(data , 1) ;
}
}
else if(str[0] == 'D'){
scanf("%d" ,&data) ;
if(s.count(data) == 0) continue ;
else {
s.erase(data) ;
add(data , -1) ;
}
}
else if(str[0] == 'Q'){
scanf("%d" , &data) ;
int st = sqrt(data) ;
int ans = INF ;
if(s.size() == 0) {
printf("-1\n") ;
continue ;
}
for(int i=1;i<=st; i++){
if(data % i == 0) {
int td = 0 ;
if(d[i]){
td = bin[lowbit(d[i])] ;
ans = min(ans , td + nums[data/i]) ;
}
if(d[data/i]){
td = bin[lowbit(d[data/i])] ;
ans = min(ans , td + nums[i]) ;
}
}
}
printf("%d\n" , ans) ;
}
}
}
}