比赛链接: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}))。
注意特殊情况:
- (n=s) 时,答案为 (n+1);
- (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;
}