​传送门​

题目大意

n个数 m个操作
‘+’代表打开对撞机
‘-’ 代表关闭对撞机
前提保证打开的对撞机两两互质
打开:
可以激活 输出“Success”
已经激活了 输出“Already on”
与j冲突了,即不能打开 输出“Conflict with j”
关闭:
可以关闭 输出“Success”
已经关闭了 输出“Already off”

思路

找到每个的质因子,在打开时判断是否有质因子已经打开的就好了

代码

///打表最小质因子

bool vis[maxn];//标记非素数,0是素数
int primer[maxn/10];//存素数
int cnt=0;//记录素数个数,
void find_primer(){
for(int i=2;i <=maxn;i++){
if(!vis[i])primer[cnt++]=i;
for(int j=0;j<cnt&&primer[j]*i<=maxn;j++){
vis[i*primer[j]]=1;//筛
if(i%primer[j]==0)break;//关键!!!找到i*primer[j]的最小质因子primer[j],退出
}
}
}

vector<int> a[maxn];
void ask(int x){
int j=0;
int xx=x;
for(int i=0;primer[i]*primer[i]<=x;i++){
if(x%primer[i]==0){
while(x%primer[i]==0){
x/=primer[i];
}
a[xx][j++]=primer[i];
}
}
if(x>1)a[xx][j++]=x;
}
int n,m;
void init(){
a[1].push_back(1);
for(int k=2;k<=n;k++){
if(!vis[k]) a[k].push_back(k);
else {
int xx=k;
int x=k;
for(int i=0;primer[i]*primer[i]<=x;i++){
if(x%primer[i]==0){
while(x%primer[i]==0){
x/=primer[i];
}
a[xx].push_back(primer[i]);
}
}
if(x>1)a[xx].push_back(x);
}
}
}
vector<int>v[maxn];
int mp2[maxn];//想打开没打开
int mp3[maxn];//打开的
int mp[maxn];
int main(){scanf("%d%d",&n,&m);
find_primer();
init();
memset(mp,0,sizeof mp);
char op[10];
int x;
memset(mp2,0,sizeof mp2);
memset(mp3,0,sizeof mp3);
while(m--){
cin>>op>>x;
if(op[0]=='+'){//将他打开
if(mp3[x]==1){
puts("Already on");
continue;
}
int flag=0;
int j;
for(int i=0;i<a[x].size();i++){
//cout<<mp[a[x][i]]<<endl;
if(mp[a[x][i]]){
flag=1;
j=i;
break;
}
}
if(flag==0){
for(int i=0;i<a[x].size();i++){
mp[a[x][i]]=1;
v[a[x][i]].push_back(x);
}
mp3[x]=1;
puts("Success");
}
else{
mp2[x]++;
printf("Conflict with %d\n",v[a[x][j]].front());
}
}
else{
if(mp3[x]==0){
puts("Already off");
continue;
}
else{
puts("Success");
mp3[x]=0;
for(int i=0;i<a[x].size();i++){
mp[a[x][i]]=0;
v[a[x][i]].clear();
}
}
}
}
}