2021年度训练联盟热身训练赛第五场

传送门:又是被队友直接带飞的一天,最后7题rank54左右。

A:Binary Seating

题意:有两个教室0,1。老师在教师1监考,每个学生等概率的进入其中一个考场,学生i答题时间为ti(1<=ti<=1000,n个学生1<=n<=40)。学生考完之后老师才能够出来,问老师出来的时间的期望。

题解:共2^n中情况,排序之后,最大值为t1的事件有2^0中可能,最大值为t2有2^1,。。。为ti有2^(i-1)中可能,及ti一定取,ti之前的数有2^(i-1)种取法。

代码:

#include<bits/stdc++.h>

#define int long long
using namespace std;
const int maxn=40+10;
int n,a[maxn];
signed main(){
    cin>>n;
    int sum=1,x=1,ans=0;
    for(int i=1;i<=n;i++) cin>>a[i],sum*=2;
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        ans+=x*a[i],x*=2;
    }
    printf("%.8lf\n",1.0*ans/sum);
    return 0;
}

B:Cutting Corners

题意:给定两个整数h,w(1~100),分别为矩形的长和宽,求h+w-sqrt(h*h+w*w)。

代码:

#include<bits/stdc++.h>

#define int long long
using namespace std;
int h,w;
signed main(){
    cin>>h>>w;
    printf("%.9lf\n",h+w-sqrt(h*h+w*w));
    return 0;
}

C:Ducky Debugging

题意略,队友在看。

代码:

#include "bits/stdc++.h"
#define int long long
using namespace std;
string s, s1 = "I quacked the code!";
signed main() {
    while (1) {
        getline(cin, s);
        int len = s.length();
        if (s == s1) break;
        if (s[len - 1] == '.')
            cout << "*Nod*\n";
        else if (s[len - 1] == '?')
            cout << "Quack!\n";
    }
    return 0;
}

D:Eightgon

*****

E:

大佬代码:Figure Skating

#include "bits/stdc++.h"
using namespace std;
int n, cnt;
string s, ans;
map<string, int> p;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s;
        p[s] = i;
    }
    for (int i = 1; i <= n; i++) {
        cin >> s;
        if (p[s] - i > cnt) cnt = p[s] - i, ans = s;
    }
    if (cnt == 0)
        cout << "suspicious";
    else
        cout << ans;

    return 0;
}

F:Group Project

题意:一开始我们读错题了。给定n个人(2~1000),m个xi,yi(xi-yi不能匹配),问最多有多少个匹配对。

开始忽略了条件:保证所有的人可以分为两个组,其中每个组中的人可以两两匹配。

题解:那么答案为n/2(向下取整)。当且仅当只有两个并查集组,且这两个并查集组大小都为奇数,而且任意一个并查集组中的数都与另一个并查集组中的数联通才会n/2-1。

敌人的敌人就是自己的朋友,一个点的所有其他连点一定在一个并查集中。注意,最后可能并不是所有数都属于特定的并查集组,如果出现这种情况,那么可以自由分配,答案一定为n/2。

代码:

#include <bits/stdc++.h>
#define pb push_back

using namespace std;
const int maxn = 2e5 + 10;

int n, m;
int u, v, cnt, ans;
vector<int> g[maxn];
int fa[maxn], dep[maxn], f[maxn];

map<int, int> mp;
int find(int x) { return (x == fa[x]) ? x : fa[x] = find(fa[x]); }
void merge(int x, int y) {
    int fx = find(x), fy = find(y);
    if (fx == fy) return;
    if (dep[fx] < dep[fy])
        fa[fx] = fy;
    else {
        fa[fy] = fx;
        if (dep[fx] == dep[fy]) dep[fy]++;
    }
}
signed main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> u >> v;
        g[u].pb(v), g[v].pb(u);
    }
    for (int i = 1; i <= n; i++) fa[i] = i;
    for (int i = 1; i <= n; i++) {
        int x = g[i][0];
        for (auto j : g[i]) merge(x, j);
    }
    ans = n / 2;
    for (int i = 1; i <= n; i++) f[i] = find(i), mp[f[i]]++;
    if (mp.size() == 2 && n % 2 == 0) {
        int cnta[2], a[2], ca = 0;
        for (auto i : mp) a[ca] = i.first, cnta[ca++] = i.second;
        // cout << ">>>" << i.first << " " << i.second<<endl;
        if (cnta[0] % 2 == 1) {
            ans -= 1;
            int f0 = 0;
            for (int i = 1; i <= n; i++) {
                if (f[i] == a[1]) continue;
                if (cnta[1] > g[i].size()) f0 = 1;
            }
            ans += f0;
        }
    }
    cout << ans << endl;
    return 0;
}

G:Human Pyramid

***

H:In-place Sorting

题意:n个数(1<=n<=10000),ai(1<=i<=n)在1~18。每个数中的6,9可以互换,问有没有一种可能使a1,a2,,,,,an为不下降序列。如果能就打印出来,否则打印不可能。

题解:我的思路也挺简单的,最开始把所有6改为9,然后从最高位开始,每次取小于上一个数的最大值,如果每次都能取到,那就ok,否则就不ok(至于怎么取,我的是模拟,挂了emmm)。

代码(我的代码最后还是没改出来,上大佬队友代码):

#include "bits/stdc++.h"
using namespace std;
const int N = 1e4 + 5;
long long n, len, siz[N], d[N];
string s[N];
string s1;
bool check(long long x, int pos) {
    s1.clear();
    int xb = 0;
    s1 = s[pos];
    for (int i = s1.length() - 1; i >= 0; i--) {
        if (s1[i] == '6') {
            if (x & 1) s1[i] = '9';
            x >>= 1;
        }
    }
    bool ok = 1;
    if (s1.length() > s[pos - 1].length()) return true;
    if (s1.length() < s[pos - 1].length()) return false;
    for (int i = 0; i < s1.length(); i++) {
        if (s1[i] > s[pos - 1][i]) return true;
        if (s1[i] < s[pos - 1][i]) return false;
    }
    return true;
}
int main() {
    d[0] = 1;
    for (int i = 1; i <= 100; i++) d[i] = d[i - 1] * 2;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> s[i];
    }
    for (int i = 1; i <= n; i++) {
        len = s[i].length();
        for (int j = 0; j < len; j++)
            if (s[i][j] == '9' || s[i][j] == '6') s[i][j] = '6', siz[i]++;
    }

    for (int i = 2; i <= n; i++) {
        long long r = d[siz[i]] - 1, l = 0;
        while (l < r) {
            long long mid = (l + r) / 2;
            if (check(mid, i))
                r = mid;
            else
                l = mid + 1;
        }
        if (!check(l, i)) {
            cout << "impossible";
            return 0;
        }
        s[i] = s1;
    }
    printf("possible\n");
    for (int i = 1; i <= n; i++) cout << s[i] << "\n";
    return 0;
}

I:Jam-packed

题意:n个罐子,每个箱子最多装k个罐子,问装的最少的箱子最多装多少罐子。

题解:我二分,队友直接输出答案emm。

代码:

#include "bits/stdc++.h"
using namespace std;
long long n,k,ans,cnt,tmp;

int main(){
	cin>>n>>k;
	if(n%k==0)	cout<<k;
	else		cout<<n/(n/k+1);
	return 0;
}
#include <bits/stdc++.h>

#define int long long
#define dbg(x) cout << #x << "===" << x << endl
#define mst(a, x) memset(a, x, sizeof(a))
#define pb push_back

using namespace std;
const int maxn = 5e2 + 10;

int n, k;
bool ok(int x) {
    int c = n / x;
    if (c * x == n) return true;
    int y = n % x;
    int yy = y / c;
    if (y % c > 0) yy++;
    if (c * x < n && x + yy <= k) return true;
    return false;
}
signed main() {
    cin >> n >> k;
    if (n <= k) {
        cout << n << endl;
        return 0;
    }
    int l = 1, r = k;
    while (l < r) {
        int mid = (l + r + 1) / 2;
        if (ok(mid))
            l = mid;
        else
            r = mid - 1;
    }
    cout << l << endl;
    return 0;
}

J:Kangaroo Commotion

***

ps:::题都没看的题,没必要补。还不如刷kuangbin来得实在。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值