看完题以后,想到的肯定是大模拟。但是如果裸的模拟是肯定会超时的。那我么就来想一下,裸的大模拟瓶颈在哪??
判断是否冲突。
由于判断是否冲突就是判断两数是否互质,所以我们可以自然地想到:将每个数分解因子(当然,分解质因子肯定更好,时间复杂度会更优),然后将这些因子存起来,每次新开启一个机器,就判断这个新机器的因子在已经存好的因子中是否出现过。当然,质数要特判一下。
在代码实现上,肯定还会有其它的细节。具体见 c o d e code code:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, m;
string S[4] = {"Success", "Already on", "Already off", "Conflict with "};
bool f[maxn];//记录机器状态
set < int > s;//存所有出现过的因子
vector < int > son[maxn];//son[i]表示有哪些开启的机器包含因子i
struct my_str {
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
inline int gcd(int x, int y) {
if(x < y) swap(x, y);
while(y) {
int temp = x;
x = y;
y = temp % y;
}
return x;
}
void work() {
n = read(), m = read();
for(int i = 1; i <= m; i ++) {
char op;
scanf("\n%c", &op);
if(op == '+') {
int x = read();
if(f[x]) {//已开启
cout << S[1] << endl;
continue;
}
bool flag = 0;
set < int >::iterator it;
int K = sqrt(x);
for(int j = 2; j <= K; j ++) {//将新机器分解因子
if(x % j == 0) {
if(s.find(j) != s.end()) {//找到了
cout << S[3];
printf("%d\n", son[j][0]);//随意输出一个即可
flag = 1;
break;
}
if(x / j != j) {
if(s.find(x / j) != s.end()) {
cout << S[3];
printf("%d\n", son[x / j][0]);
flag = 1;
break;
}
}
}
}
if(flag) continue;
if(s.find(x) != s.end()) {//特判素数
cout << S[3];
printf("%d\n", son[x][0]);
continue;
}
f[x] = 1;
cout << S[0] << endl;
K = sqrt(x);
flag = 0;
for(int j = 2; j <= K; j ++) {//存入新机器的因子
if(x % j == 0) {
flag = 1;
son[j].push_back(x);
s.insert(j);
if(x / j != j) {
son[x / j].push_back(x);
s.insert(x / j);
}
}
}
if(!flag) son[x].push_back(x), s.insert(x);//特判素数
}
else {
int x = read();
if(!f[x]) {//已关闭
cout << S[2] << endl;
continue;
}
f[x] = 0;
cout << S[0] << endl;
int K = sqrt(x);
bool flag = 0;
for(int j = 2; j <= K; j ++) {
if(x % j == 0) {
flag = 1;
if(son[j].size() > 1) {
vector < int >::iterator it = find(son[j].begin(), son[j].end(), x);//在vector中查找数字x
it = son[j].erase(it);//删除函数基本用法,vector的erase函数是有返回值的,返回删除后的下一个迭代器
}
else son[j].clear(), s.erase(j);
if(x / j != j && son[x / j].size() > 1) {
vector < int >::iterator it = find(son[x / j].begin(), son[x / j].end(), x);
it = son[x / j].erase(it);
}
else son[x / j].clear(), s.erase(x / j);
}
}
if(!flag && son[x].size() > 1) {
vector < int >::iterator it = find(son[x].begin(), son[x].end(), x);
it = son[x].erase(it);
}
else son[x].clear(), s.erase(x);
}
}
}
}code;
int main() {
code.work();
return 0;
}