2020 KAIST 10th ICPC Mock Contest (XXI Open Cup. Grand Prix of Korea. Division 2)_组队训练
2020 KAIST 10th ICPC Mock Contest (XXI Open Cup. Grand Prix of Korea. Division 2)
B. Bombs In My Deck
D. Fix Wiring
F. Square, Not Rectangle
H. Mock Competition Marketing
K. Sewing Graph
B.签到题,直接暴力。
void run(){ int a,b,c; cin>>a>>b>>c; if(b*5<c){ printf("1"); return; }else{ double ans=0.00; int num=(c-1)/5; for(int i=0;i<=num;i++){ int A=a,B=b; int cc=i; double now=1.000; while(cc--){ now=now*1.000*B/A; B--; A--; } now=now*1.000*(A-B)/A; //cout<<ans<<endl; ans=ans+now; } printf("%.10f",ans); } }
D- Fix Wiring
题目大意:有n个点,连一张完全图。现在有n*(n-1)/2个值,你需要由某种策略给每条边赋上这些值,使得建立一个最小生成树的费用最小 和 最大(两问),求最小值和最大值是多少。
最小值显然就是选前n-1条最小的边。
最大值就是我们需要使得小的边尽可能没用。那么我们假设最小生成树应当是从点1连点2,点2连点3…点n-1连点n,我们每次按次序往里面加一个点。
我们可以发现,每次加入一个点的时候,总要向前n-1个点连边。而此时,举个例子来说,如果点i连上了通往点1的边,那么点1到点i这条中间按着顺序直接连的i-1条边中有可能就有一条边不再是最小生成树上的边。
那么我们就有做题策略了,将边从小到大排序之后进行使用。按照次序加点,每次点i向前连边,一直连到通往点1的边(这样是保证i到i-1的边是最小边以使其一定在最小生成树上)。
ll c[maxn]; void run(){ int n=rd(); int m=n*(n-1)/2; rep(i,1,m) c[i]=rdll(); sort(c+1,c+1+m); ll ans=0; rep(i,1,n-1){ ans+=c[i]; } ll sum=0; int cnt=0; rep(i,2,n){ for(int j=i-1;j>=1;j--){ cnt++; if(j+1==i) sum+=c[cnt]; } } cout<<ans<<" "<<sum; } signed main() { // int t=rd(); // while(t--){ // run(); // } run(); return 0; }
F. Square, Not Rectangle
题意:横向长度为n,纵向长度为h[i]的图形,最大能构成的矩阵的边长为多少。
题解:直接二分答案,left=1,right=1e9.然后判断mid是否存在即可.
#include<bits/stdc++.h> #define ll long long using namespace std; ll h[300300]; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>h[i]; } int left = 1,right = 1000000000; int maxx = 1; while(left<=right) { int mid = (left+right)/2; //cout<<left<<" "<<right<<" "<<mid<<endl; bool flag = false; int ans = 0; for(int i=1;i<=n;i++) { //if(mid==3)cout<<i<<" "<<ans<<endl; if(h[i]>=mid) { ans++; } else { if(ans>=mid) { flag = true; break; } ans = 0; } if(ans>=mid) { flag = true; break; } //if(mid == 2) cout<<ans<<endl; } if(flag) { //cout<<mid<<endl; maxx = max(maxx,mid); left = mid + 1; } else right = mid - 1; } cout<<maxx<<endl; }
H.待补
K.待补