寒假ACM集训复习总结Day1-helman
B题
一开始是没想出来的。
讲的是用k根绷带粘住n个坏掉的地方,求用最少的绷带
原本的想法是将每种可能的粘法穷举出来,求最少的绷带
但是换个方向看,每个坏掉的地方都要粘住,意味着每处都用了一的绷带
此时用的绷带数就是n,每填补两个坏处之间的距离,就会使得绷带数减一
要想只用k根绷带,并且使绷带总长最短,就是在原本n的绷带长度上加上n-k个最短距离
于是答案就很简单了
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+7; int main(){ int n,m,k; int a[maxn],b[maxn]; while(cin>>n>>m>>k){ cin>>a[0]; for(int i=1;i<n;i++){ cin>>a[i]; b[i]=a[i]-a[i-1]-1; } sort(b+1,b+n); int ans=0; for(int i=1;i<=n-k;i++) ans+=b[i]; cout<<ans+n<<endl; } return 0; }
D题
D题一开始也没想出来
讲的是给出n个超级英雄的能量,操作是减少一个英雄或增加一个英雄的1点能量
每个英雄最多操作k次,总共操作最多m次,求最大的平均能量
感觉可以算,但不知道怎么算
实际上这个题思路应该是一个个试
首先留下第一强的英雄,如果总操作数少于剩下的英雄数(想删掉剩下的英雄),就继续添加强的英雄
因为无论怎么操作,都不能去掉目前添加的这些英雄
为什么第一目的的删掉英雄而不是强化英雄呢
是因为理想情况下能量n和n-1的英雄,删掉弱的后平均值是n,强化一点后平均值是n
而当强的英雄和弱的英雄差距变大时,删掉弱的增长更快
而当总操作数不少于剩下的英雄数时,就可以考虑删掉剩下的英雄
将剩下的英雄全部删掉,多出的操作强化目前的英雄,求得这种状况下的平均值
接着不断加入新的强英雄,删掉剩下的英雄,求得当前情况下的平均值
最后比较得到最大的平均值
#include<bits/stdc++.h> using namespace std; const int Nmax=1e6+7; typedef long long ll; int a[Nmax]; int main(){ int n,k,m; cin>>n>>k>>m; for(int i=0;i<n;i++){ cin>>a[i]; } ll sum=0; double ans=0; sort(a+0,a+n); for(int i=n-1;i>=0;i--){ sum+=a[i]; int num=n-i; if(m>=(n-num)){ ans=max(ans,(double)(sum+min((double)num*k,((double)m-(n-num))))/(double)num); } } printf("%lf",ans); return 0; }
E题
E题是给出x,y(x<=y)的因子,让我们还原这两个数
这就需要思考一下
一个数的因子包含自己,所以这堆数里最大的数就是y
接下来又分成几种情况
x是y的因子
那么出现两个相邻且相等的数就是x
x不是y的因子
那么出现一个不是y因子的数就是x
#include <bits/stdc++.h> using namespace std; int main() { //freopen("1.in","r",stdin); int n,d[300]; cin>>n; for(int i=1;i<=n;i++) cin>>d[i]; sort(d+1,d+1+n); printf("%d ",d[n]); for(int i=n-1;i>=1;i--) { if(d[n]%d[i]!=0) { printf("%d",d[i]); return 0; } else if(d[i]==d[i-1]||d[i]==d[i+1]) { printf("%d",d[i]); return 0; } } }