好题分享:对撞机(luogu P1871)

题面

看完题以后,想到的肯定是大模拟。但是如果裸的模拟是肯定会超时的。那我么就来想一下,裸的大模拟瓶颈在哪??

判断是否冲突。

由于判断是否冲突就是判断两数是否互质,所以我们可以自然地想到:将每个数分解因子(当然,分解质因子肯定更好,时间复杂度会更优),然后将这些因子存起来,每次新开启一个机器,就判断这个新机器的因子在已经存好的因子中是否出现过。当然,质数要特判一下

在代码实现上,肯定还会有其它的细节。具体见 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; }

__EOF__

本文作者best_brain
本文链接https://www.cnblogs.com/best-brain/p/18006577.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   best_brain  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示