AtCoder Beginner Contest 044 题解

比赛链接:https://atcoder.jp/contests/abc044

A - Tak and Hotels (ABC Edit)

题目大意:
\(N\) 天旅馆,前 \(K\) 天每晚 \(X\) 元,接下来每晚 \(Y\) 元。问:一共花多少钱?

解题思路:
直接一个if判断即可。

示例程序:

#include <bits/stdc++.h>
using namespace std;
long long N, K, X, Y;
int main() {
    cin >> N >> K >> X >> Y;
    if (N <= K) cout << N * X << endl;
    else cout << K * X + (N - K) * Y << endl;
    return 0;
}

B - Beautiful Strings

题目大意:
判断一个字符串中的每个字符出现次数是否都为偶数次。

解题思路:
开个 cnt 数组标记一次每个字符出现次数。

示例程序:

#include <bits/stdc++.h>
using namespace std;
char s[110];
int n;
int main() {
    cin >> s;
    n = strlen(s);
    sort(s, s+n);
    for (int i = 0; i < n; i += 2) if (s[i] != s[i+1]) {
        puts("No");
        return 0;
    }
    puts("Yes");
    return 0;
}

C - Tak and Cards

题目大意:
求有多少种方案能够从 \(N(1 \le N \le 16)\) 个数中选出一些数,其平均数为 \(A\)

解题思路:
DP。设 \(f_{i,j,k}\) 表示前 \(i\) 个数总和为 \(j\),数量为 \(k\) 的方案数,则状态转移方程为:

  • \(f_{0,0,0}=1\)
  • \(f_{i,j,k} = f_{i-1,j,k} + f_{i-1, j-a[i],k-1}\)(我这里用 \(a[i]\) 表示数组第 \(i\) 个数)

示例程序:

#include <bits/stdc++.h>
using namespace std;
int n, A, a[55], sum;
long long f[2550][50], ans;
int main() {
    cin >> n >> A;
    f[0][0] = 1;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
        sum += a[i];
        for (int j = sum; j >= a[i]; j --) {
            for (int k = 1; k <= i; k ++) {
                f[j][k] += f[j-a[i]][k-1];
            }
        }
    }
    for (int i = 1; i <= n; i ++) ans += f[i*A][i];
    cout << ans << endl;
    return 0;
}

D - Digit Sum

题目大意:
给你整数 \(n\)\(s\),判断是否存在一个整数 \(b\),使得 \(n\)\(b\) 进制下的数位和等于 \(s\)

解题思路:

首先枚举所有 \(\le \sqrt{n}\)\(b\)

其次考虑所有 \(b \gt \sqrt{n}\) 的情况,此时 \(n \div s\) 的结果为两位数,枚举较高位(不超过 \(\sqrt{n}\))。

注意特殊情况:

  1. \(n=s\) 时,答案为 \(n+1\)
  2. \(s=1\) 时,\(n\) 为一个候选答案。

示例程序:

#include <bits/stdc++.h>
using namespace std;
long long n, sn, s, ans = -1;
// 判断a进制的情况下数位和是否为s
bool check1(long long a) {
    long long tmp = 0, m = n;
    while (m) {
        tmp += m % a;
        m /= a;
    }
    return tmp == s;
}
// 返回b>sqrt(n)时,较高位为a对应的进制
long long check2(long long a) {
    long long b = n - (s - a);
    if (b % a) return -1;
    b /= a; // 获得进制b
    if (b <= sn) return -1;  // 此处进制应该大于根号n
    if (s-a >= b) return -1; // 余数大于等于除数
    return b;
}
int main() {
    cin >> n >> s;
    if (n == s) {
        cout << n+1 << endl;
        return 0;
    }
    sn = sqrt(n);
    for (long long i = 2; i <= sn; i ++) {
        if (check1(i)) {
            cout << i << endl;
            return 0;
        }
    }
    for (long long i = 1; i < sn && i <= s; i ++) {
        long long tmp = check2(i);
        if (tmp == -1) continue;
        if (ans == -1 || ans > tmp) ans = tmp;
    }
    if (ans == -1 && s == 1) ans = n;
    cout << ans << endl;
    return 0;
}
posted @ 2021-03-02 21:02  quanjun  阅读(145)  评论(0)    收藏  举报