文章目录
AtCoder Beginner Contest 044
A - Tak and Hotels (ABC Edit)
题意:
题解:
代码:
#include <bits/stdc++.h>
#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') w = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int const MAXN = 2e5 + 10;
int n, m, T, k, x, y;
signed main() {
cin >> n >> k >> x >> y;
int res = 0;
if (k < n) res = k * x + y * (n - k);
else res = n * x;
cout << res;
return 0;
}
B - Beautiful Strings
题意:
题解:
代码:
#include <bits/stdc++.h>
#define int long long
#define debug(x) cout << #x << " = " << x << endl;
using namespace std;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') w = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int const MAXN = 2e5 + 10;
int n, m, T;
map<char, int> cnt;
signed main() {
string s;
cin >> s;
for (int i = 0; i < s.size(); ++i) {
cnt[s[i]]++;
}
for (int i = 0; i < s.size(); ++i) {
if (cnt[s[i]] % 2) {
cout << "No";
return 0;
}
}
cout << "Yes";
return 0;
}
C - Tak and Cards
题意: 典型的背包计数问题
题解:
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int const N = 1e6 + 10;
int f[100][10000];
int n, m;
signed main() {
cin >> n >> m;
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
for (int j = i; j > 0; j--) {
for (int k = m * n; k >= x; k--) {
f[j][k] += f[j - 1][k - x];
}
}
}
int res = 0;
for (int i = 1; i <= n; ++i) {
res += f[i][i * m];
}
cout << res;
return 0;
}
D - Digit Sum
题意: 给定函数表达式:
f(b, n) = n, when n < b
f(b, n) = f(b, floor(n / b)) + (n mod b), when n >= b
该表达式意思是求出n在b进制下的每位和。比如:f(10, 87654) = 8 + 7 + 6 + 5 + 4 = 30
现在给定n和s,让找出一个最小的b(b >= 2)使得 f(b, n) = s。 1 < = n < = 1 0 11 , 1 < = s < = 1 0 11 1<=n<=10^{11}, 1<=s<=10^{11} 1<=n<=1011,1<=s<=1011
题解:
假设 x 0 , x 1 , . . . , x m x_0, x_1, ...,x_m x0,x1,...,xm 为n在b进制下的各位数字( x 0 x_0 x0为最低位),那么就有:
x 0 + x 1 ∗ b + . . . + x m ∗ b m = n x_0+x_1*b+...+x_m*b^m=n x0+x1∗b+...+xm∗bm=n
x 0 + x 1 + . . . + x m = s x_0+x_1+...+x_m=s x0+x1+...+xm=s
对于这种题目,产生幂次方,可以以2的幂次为边界分类讨论:
-
b<=sqrt(n)
那么可以枚举b,然后判断上面2个式子是否同时满足
-
b>sqrt(n)
则式子变为:
x 0 + x 1 ∗ b = n x_0+x_1*b=n x0+x1∗b=n
x 0 + x 1 = s x_0+x_1=s x0+x1=s
推导得: x 1 ∗ ( b − 1 ) = n − s x_1*(b-1)=n-s x1∗(b−1)=n−s
那么转而去枚举n-s的因子x1,然后判断是否成立即可。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int f(int b, int n) {
if (n < b) return n;
return f(b, n / b) + n % b;
}
signed main() {
int n, s;
cin >> n >> s;
if (n < s) {
cout << "-1" << endl;
return 0;
}
if (n == s) {
cout << n + 1 << endl;
return 0;
}
int up = (int)sqrt(n) + 1;
for (int i = 2; i <= up; i++)
if (f(i, n) == s) {
cout << i << endl;
return 0;
}
n -= s;
int Minb = 1e11;
for (int p = 1; p * p <= n; p++)
if (n % p == 0) { // 如果是因子
int b = n / p + 1;
int a0 = s - p;
int a1 = p;
if (b >= 2 && a0 >= 0 && a0 < b && a1 < b)
Minb = min(Minb, b);
}
if (Minb == 1e11) cout << "-1" << endl;
else cout << Minb << endl;
return 0;
}