P9473 [yLOI2022] 西施江南 的题解
Whispering_H · · 题解
(此题解未通过,仅作总结)
题目大意
传送门
意思很简洁,不讲。
大体思路
可以发现,只要这 Yes,否则是 No。
注意还要特判 Yes。
想到这里,我就打了一个
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
return x * f;
}
int T, n, cnt = 0;
int a[500007];
bool nprime[100000007];
inline int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); }
int main() {
T = read();
while(T--) {
n = read(); cnt = -1;
ll maxx = 0;
for(int i = 1; i <= n; i++) {
a[i] = read();
maxx = max(maxx, (ll)a[i]);
}
if(n <= 2) { printf("Yes\n"); continue; }
bool flag = 1;
for(int i = 1; i <= n && flag == 1; i++)
for(int j = i + 1; j <= n; j++)
if(gcd(a[i], a[j]) > 1) { printf("No\n"); flag = 0; break; }
if(flag == 1) printf("Yes\n");
}
return 0;
}
评测记录
用时:23.45s
内存:3.54MB
这个暴力应该已经做到极致了,那么我们考虑其他做法。
我们发现,如果换一个角度思考,分解质因数,开一个
于是正解就上来了!
#include <bits/stdc++.h>
using namespace std;
int T, n, maxx = 0;
int a[500007];
bool vis[100000007];
int main() {
cin >> T;
while(T--) {
cin >> n;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
cin >> a[i];
if(n <= 2) { cout << "Yes\n"; continue; }
bool flag = 1;
for(int i = 1; i <= n && flag == 1; i++) {
for(int j = 2; j * j <= a[i]; j++) {
if(a[i] % j != 0) continue;
if(vis[j] == 1) { cout << "No\n"; flag = 0; break; }
while(a[i] % j == 0) a[i] /= j;
vis[j] = 1;
}
if(a[i] != 0) {
if(vis[a[i]] == 1) { cout << "No\n"; flag = 0; break; }
vis[a[i]] = 1;
}
}
if(flag) cout << "Yes\n";
}
return 0;
}
评测记录
用时:10.64s
内存:97.71MB
我们过了这题,可是美中不足的是,用时和内存都太大了,我们可以怎么优化呢?
优化 1
读入优化:加上快读,后面输出变成 printf 即可。
篇幅原因,代码我就不给了。
评测记录
用时:9.52s
内存:97.70MB
我们发现时间优化了整整
优化 2
我们发现时间上面的一个巨大瓶颈在于 memset 上面,因为我们需要将一个
于是我们定义一个 memset(vis, 0, maxx + 1); 这样就可以节省掉很多时间。
#include <bits/stdc++.h>
using namespace std;
int T, n, maxx = 0;
int a[500007];
bool vis[100000007];
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
return x * f;
}
int main() {
T = read();
while(T--) {
n = read();
memset(vis, 0, maxx + 1);
maxx = 0;
for(int i = 1; i <= n; i++)
a[i] = read();
if(n <= 2) { printf("Yes\n"); continue; }
bool flag = 1;
for(int i = 1; i <= n && flag == 1; i++) {
for(int j = 2; j * j <= a[i]; j++) {
if(a[i] % j != 0) continue;
if(vis[j] == 1) { printf("No\n"); flag = 0; break; }
while(a[i] % j == 0) a[i] /= j;
vis[j] = 1;
maxx = max(maxx, j);
}
if(a[i] != 0) {
if(vis[a[i]] == 1) { printf("No\n"); flag = 0; break; }
vis[a[i]] = 1;
maxx = max(maxx, a[i]); //注意这里也要加!
}
}
if(flag) printf("Yes\n");
}
return 0;
}
评测记录
用时:4.42s
内存:97.66MB
我们可以发现,时间减了有
其中还有一些小优化我就不说了,应该影响不大。
但是我们发现空间还是非常的大,但是由于作者太弱,想不出其他优化的方法了(感觉可以把
好了,题解就到这了,如果有更好的此类方法的优化,欢迎私信作者!