0
点赞
收藏
分享

微信扫一扫

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;
}


举报

相关推荐

0 条评论