CF -- 677(div3):A~E题(题解)

A. Boring Apartments

签到题

AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char s[5];
void solve() {
    scanf("%s", &s);
    int len = strlen(s);
    printf("%d\n", (s[0] - '0' - 1) * 10 + (len + 1) * len / 2);
}
int main() {
    int t;
    scanf("%d", &t);
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}
B. Yet Another Bookshelf
思路

签到题,取出前导零和后导零,记录中间有多少个零,可以先将两边的1移动到一起,然后一起往中间移动,也就是记录中间中间有多少个零。

AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 100 + 5;
int a[maxn];
void solve() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", &a[i]);
    }
    int l, r;
    for (l = 0; l < n; ++l) {
        if (a[l]) {
            break;
        }
    }
    for (r = n - 1; r >= 0; --r) {
        if (a[r]) {
            break;
        }
    }
    int ans = 0;
    for (int i = l; i <= r; ++i) {
        if (a[i] == 0) {
            ans++;
        }
    }
    printf("%d\n", ans);
    //puts("--------");
}
int main() {
    int t;
    scanf("%d", &t);
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}
C - Dominant Piranha: 简单贪心
思路:

签到题,直接记录最大值的边界位置即可,例如5 5 4 3 5, 2和5都是边界位置,这些边界位置都是优势食人鱼。

AC代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
int a[maxn];
void solve() {
    int n;
    scanf("%d", &n);
    int mx = 0;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        mx = max(mx, a[i]);
    }
    a[0] = a[n + 1] = mx;
    int ans = -1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] == mx && (a[i - 1] != mx || a[i + 1] != mx)) {
            ans = i;
            break;
        }
    }
    printf("%d\n", ans);
    //puts("--------");
}
int main() {
    int t;
    scanf("%d", &t);
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}
D. Districts Connection: 暴力
思路:

直接暴力找两个不同的值连接起来即可。

AC代码
#include<stdio.h>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
int a[maxn], vis[maxn];
void solve() {
    int n;
    set<int> st;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        st.insert(a[i]);
    }
    if (st.size() == 1) {
        puts("NO");
        return;
    }
    puts("YES");
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; ++i) {
        if (vis[i]) continue;
        for (int j = 1; j <= n; ++j) {
            if (i == j) continue;
            if (a[i] != a[j]) {
                printf("%d %d\n", i, j);
                vis[j] = true;
                break;
            }
        }
    }
}
int main() {
    int t;
    scanf("%d", &t);
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}
E. Two Round Dances 组合数+圆排列
思路:

圆排列

循环排列,如果以r为周长,则不同的方案数为,A(r, n) / r = r, 如果r == n,则方案数为(n - 1)!;
左集合:先从n中选n/2个,再进行圆排列,一共有C(n / 2, n) * A(n / 2, n / 2) / (n / 2) == > C(n / 2, n) * (n / 2 - 1)!;
右集合:由于前面已经选了n/2个,所以右集合的元素固定,然后进行圆排列 A(n / 2, n / 2) / (n / 2) == > (n / 2 - 1)!;
将左集合的方案数*右集合的方案数乘起来就是总方案数了,但我们仔细想一想真的是这样吗,其实不然,但我们选取一半的集合作为
左集合的时候,右集合唯一, 但是会重复算一次,举个简单的例子,n = 4时,我们不考虑圆排列的情况下,[1, 3], [2, 4]和[2, 4],[1, 3]
是不是一样的,所以我们最后需要除以2.

AC代码
#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
//求组合数C(m, n);
ll cal(int m, int n) {
    if (m == 0 || m == n) {
        return 1;
    }
    if (n < m) {
        return 0;
    }
    return cal(m - 1, n - 1) + cal(m, n - 1);
}
void solve() {
    int n;
    scanf("%d", &n);
    ll C = cal(n / 2, n);
    ll A = 1;
    for (ll i = 1; i < n / 2; ++i) {
        A *= i;
    }
    printf("%lld\n", C * A * A / 2);
    //puts("--------");
}
int main() {
    int t = 1;
//    scanf("%d", &t);
    for (int i = 0; i < t; ++i) {
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值