A:
题意:现有 a 数组,你可以执行以下操作若干次:选择一个元素,将其增加 1 或减少 1使得存在三个相等元素,求最少操作次数。
方法:sort+爆搜
我们知道,选择三个数,通过操作后,要使三个数都相等,那么所需要的操作:max-min。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
int a[N];
inline void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);int ans=9e9;
for(int i=3;i<=n;i++) ans=min(ans,a[i]-a[i-2]);//以长度为3的区间进行搜索就行
cout<<ans<<"\n";
}
int main(){
int T;cin>>T;
while(T--) solve();
}
B:
题意:现有 n 层的金字塔,第 i 层有 i 个房间。从第 i 层第 j 个房间可以到达第 i+1 层第 j 个房间或是第 j+1 个房间。现某些房间放置有火炬。并定义一个房间 (i,j) 的亮度是"所有从 (1,1) 到达 (i,j) 的路径经过的房间的集合中,放置有火炬的房间数量"。现在,请给出一种放置火炬的方案,使得:对于每一层,所有房间的亮度一致。
定义每一层第一个房间的亮度之和为金字塔的总亮度。总亮度达到最大值。
方法:我们知道,上一层的某个位置,会点亮他下一层对应的两个位置。那么我分析样例的解析就可以知道,只需要在金字塔每层的两端放上各放上一盏灯,那么就可以全部点亮金字塔。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,t;
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++){
if(i) cout<<"1 ";
for(int j=1;j<i;j++) cout<<"0 ";
cout<<1<<"\n";
}
}
}
C:
题意:给出初始集合1,2,3⋯,n,每次操作可以选择一个k删除当前集合中最小的k的倍数,代价为k.给出集合T,问最少需要多少代价才能把初始集合变为T
这里解释一下样例:1101001=1,2,4,7
方法:贪心。要使代价最少,那么我们应该选择一个数的最小因数进行操作。考虑某个需要被删除的元素,如果它能被多个 k 删除,一定是选择最小的那个 k 。删除某一个元素,不会提高删除其他元素的代价(反而可能使其他元素的删除更加便利)。因此,我们可以枚举代价 k ,如果可以删除某个元素,就放心大胆地删除它。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int t,n;
char s[N];
inline void solve(){
int n;cin>>n;
long long ans=0;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++){
for(int k=1;i*k<=n&&s[i*k]!='1';k++){
ans+=i*(s[i*k]=='0');
s[i*k]='2';//标记已经删除的数
}
}
cout<<ans<<endl;
}
int main(){
cin>>t;
while(t--) solve();
}