SXYZ-7.4训练赛
今天这场比赛把人心态考崩溃了,只考100分钟,四道思考和算法题,旁边大佬开局5分钟秒T1,我30分钟打了个T1暴力。┭┮﹏┭┮,呜呜~。T2,T4根据题意暴力。T3人手模拟了一下,完全没有任何思路,放弃。(好在没有犯低级错误)。
T1 A
最大公约数
被第一题切掉了,考场上先现推 gcd,然后手打 gcd,记得c++有个函数(但没记起来)是 __gcd()
,没有正解思路,旁边大佬已经切了,我灵光一线——DP,然而写出来样例一测,假的,这道题无法动规,子问题会影响后续答案,于是。。。。暴力喜提50分。
暴力思路:依次计算删掉每一个数的最大公约数,时间复杂度 \(O(n^2)\)。
然而正解其实也是这个思路,预先处理 gcd 的前缀和和后缀和,然后枚举删掉每一个数。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define N 200000
int n,a[N],q[N],h[N],ans=0;
int gcd(int a,int b){
if(b>a) swap(a,b);
if(b==0) return a;
else return gcd(b,a%b);
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
q[i]=gcd(q[i-1],a[i]);
}
for(int i=n;i>=1;i--){
h[i]=gcd(h[i+1],a[i]);
}
for(int i=1;i<=n;i++){
ans=max(ans,gcd(q[i-1],h[i+1]));
}
printf("%d",ans);
return 0;
}
T2 B
排序
这道题思想确实很妙,开始没有想到。
考虑到正解,每一个数 i 最后都将移动到位置 i,所以我们暴力将每一个数移到正确位置,因为每一个数必须移到正确位置,交换方法是唯一的,所以这就是最优解。
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
vector<int> v;
bool usd[N];
int n,a[N],ip[N];
signed main(){
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),ip[a[i]]=i;
for(int i=1;i<=n;i++){
if(ip[i]==i)continue;
while(ip[i]!=i){
if(usd[ip[i]-1]){
cout<<"-1\n";
return 0;
}
usd[ip[i]-1]=true;
v.push_back(ip[i]-1);
ip[i]--;
int l=a[ip[i]];
ip[l]++;
swap(a[ip[i]],a[ip[l]]);
}
}
if(v.size()!=n-1)cout<<"-1\n";
else for(auto i:v)cout<<i<<"\n";
}
T3 C
不会,真不会
T4 D
排序
还是不会,真不会,
直接上代码:
#include <cstdio>
int main() {
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
int n;
scanf("%d", &n);
printf("%d\n", n * n);
for (int i = n - 1; i>=0; --i) {
for (int j = 0; j < n; ++j) {
printf("%d\n", i);
}
}
}
刚刚去跟同学讲了一下这道题,自己又增添了不少理解,现在应该是完全理解了吧??
思想有点多,这里直接复制了,题解来源。
首先你用脑子想一下,你就会知道,如果一直盯着一个位置换,那他最后会换成0 。因为位置固定,你要交换另一个位置所需要的值也是固定的,而他被换走了,就再也换不到了。
然后你在0的前面一直操作,他最后也会变成0,而且他一定会在变成1后变成0,因为要和后一位交换。
于是你从前往后一直这样操作,最后就可以将0和1换到最前面,而且在换第0位的时候,如果你的值是 x,那他一定会被换到第 x 位。所以后面也是有序的。
然后你就做完了。