Codeforces Round #494 (Div. 3)

刚好在考完当天有一场div3,就开了个小号打了,打的途中被辅导员喊去帮忙,搞了二十分钟-_-||,最后就出了四题,题解如下:
题目链接:http://codeforces.com/contest/1003

 

题目:

思路:求众数出现的次数

代码如下:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define debug(x) cout <<"[" <<x <<"]" <<endl

const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 7;

int n;
int a[105], vis[105];

int main() {
    cin >>n;
    int mx = -1;
    for(int i = 0; i < n; i++) {
        cin >>a[i];
        vis[a[i]]++;
        if(mx < vis[a[i]]) {
            mx = vis[a[i]];
        }
    }
    cout <<mx <<endl;
    return 0;
}


 

题目:

思路:构造一个01串,其中0的个数为a,1的个数为b,中间刚好有k次01的交替,题目保证有解。模拟即可。

代码实现如下:

#include <bits/stdc++.h>
using namespace std;

int a, b, x, flag;
int vis[205];

int main() {
    cin >> a >> b >> x;
    int flag = x & 1;
    if(a >= b) {
        vis[0] = 0;
        a--;
        for(int i = 1; i < x; i++) {
            vis[i] = !vis[i-1];
            if(i & 1) b--;
            else a--;
        }
        for(int i = 0; i < x; i++) {
            cout <<vis[i];
        }
        if(flag) {
            for(int i = 0; i < a; i++) {
                cout <<"0";
            }
            for(int i = 0; i < b; i++) {
                cout <<"1";
            }
        } else {
            for(int i = 0; i < b; i++) {
                cout <<"1";
            }
            for(int i = 0; i < a; i++) {
                cout <<"0";
            }
        }
        cout <<endl;
    } else {
        vis[0] = 1;
        b--;
        for(int i = 1; i < x; i++) {
            vis[i] = !vis[i-1];
            if(i & 1) a--;
            else b--;
        }
        for(int i = 0; i < x; i++) {
            cout <<vis[i];
        }
        if(flag) {
            for(int i = 0; i < b; i++) {
                cout <<"1";
            }
            for(int i = 0; i < a; i++) {
                cout <<"0";
            }
        } else {
            for(int i = 0; i < a; i++) {
                cout <<"0";
            }
            for(int i = 0; i < b; i++) {
                cout <<"1";
            }
        }
        cout <<endl;
    }
    return 0;
}


 

题目:

思路:求长度大于等于k的连续字串的平均值的最大值,因为本题数据小,可以用n^2水过,数据大了需要用二分,这里就只贴比赛时写的n^2的代码了~先用一个前缀和来维护分子,分母用一个循环处理。

代码如下:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2 * 5007;
const double eps = 1e-8;
int n, k;
double ans;
int a[maxn], sum[maxn];

int main() {
    scanf("%d%d", &n, &k);
    sum[0] = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        sum[i] = sum[i-1] + a[i];
    }
    ans = -1;
    for(int i = 1; i <= n; i++) {
        for(int j = k; j <= n; j++) {
            double t = 1.0 * (sum[i + j - 1] - sum[i-1]) / j;
            if(t - ans >= eps) {
                ans = t;
            }
        }
    }
    printf("%.7f\n", ans);
    return 0;
}


 

题目:

题意:给你n个数,ai保证是2的幂次,q次查询,每次查询给你一个数x,问使用最少的a来组成这个数,如果无法组成就输出-1.

思路:先将ai转换成2^t,用个数组来储存;将x转换成二进制,然后从最大为开始贪心,当题目给的某一次方(t次方)不够时,就用2个t-1次方来构成一个t次方,最后判断0次方是否足够即可。用样例来解释:题目给的2的1次方有2个,2次方有2个,3次方有1个。第一个x的二进制为1000,需要一个2的3次方,题目给的刚好有一个3次方,因此答案为1;第二个x的二进制为101,需要2的2次方1个,0次方1个,2次方足够,但是没有0次方,所以答案为-1;第三个x的二进制为1110,需要1个3次方,1个2次方,1个1次方,均足够,故为3。

代码实现如下:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 7;
int n, q, t;
int a[maxn], b[maxn], num[32], p[32];
long long vis[maxn];

void prepare() {
    vis[0] = 1;
    for(int i = 1; i < 32; i++) {
        vis[i] = vis[i-1] * 2;
    }
}

int main() {
    prepare();
    cin >>n >>q;
    for(int i = 0; i < n; i++) {
        cin >>a[i];
        t = lower_bound(vis, vis + 31, a[i]) - vis;
        num[t]++;
    }
    for(int i = 0; i < q; i++) {
        cin >>b[i];
        int k = 0, ans = 0;
        while(b[i]) {
            p[k++] = b[i] % 2;
            b[i] = b[i] / 2;
        }
        for(int j = k - 1; j >= 1; j--) {
            if(num[j] < p[j]) {
                ans += num[j];
                p[j-1] += 2 * (p[j] - num[j]);
            } else {
                ans += p[j];
            }
        }
        if(num[0] < p[0]) cout <<"-1" <<endl;
        else cout <<ans + p[0] <<endl;
    }
    return 0;
}


 


 

赛后补题,一定要假装出是自己比赛时A的~

题目:

题意:生成一棵树,树的直径(本题的直径是指两节点间距离的最大值)为d,度数不超过k。

思路:首先生成一条链,此处节点分别为1~d+1,然后以这条链上的节点为根生成树,用dfs处理,此处生成的树的深度为min(i-1,d-i+1)(因为两节点间的距离不能超过d嘛~),注意处理NO的情况。

代码实现如下:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 4e5 + 7;
int n, k, d, cnt;
vector<int> G[maxn];

void dfs(int u, int deep, int mx) {
    if(deep == mx) return;
    for(int i = 0; i < k - 1 - (deep == 0) && cnt < n; i++) {
        int v = ++cnt;
        G[u].push_back(v);
        dfs(v, deep + 1, mx);
    }
}

int main() {
    cin >>n >>d >>k;
    if(k==1){
        if(n!=2 || d!=1)printf("NO\n");
        else printf("YES\n1 2\n");
        return 0;
    }
    if(d >= n) {
        cout <<"NO" <<endl;
        return 0;
    }
    for(int i = 1; i <= d; i++) {
        G[i].push_back(i+1);
    }
    cnt = d + 1;
    for(int i = 1; i <= d + 1; i++) {
        dfs(i, 0, min(i - 1, d - i + 1));
    }
    if(cnt < n) {
        cout <<"NO" <<endl;
        return 0;
    }
    cout <<"YES" <<endl;
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j < G[i].size(); j++) {
            cout <<i <<" " <<G[i][j] <<endl;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值