题目链接
(A. Berland Poker)
(Description:)
给定 (n) 张牌,其中有 (m) 张特殊的牌,把所有牌平均分给 (k) 个人,问你手中的特殊牌的数量 (-(k - 1)) 个人中拥有最多特殊牌的数量的最大值是多少?
(Solution:)
先把特殊牌分给你,其他人在平均分即可。
(Code:)
/*
@Author: nonameless
@Date: 2020-05-29 09:20:42
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
int main(){
int t; cin >> t;
while(t --){
int n, m, k;
cin >> n >> m >> k;
int cnt = n / k;
if(cnt >= m) cout << m << endl;
else{
cnt -= (m - cnt) / (k - 1) + ((m - cnt) % (k - 1) != 0);
cout << cnt << endl;
}
}
return 0;
}
(B. New Theatre Square)
(Description:)
给定 (n imes m) 的矩阵,让你来用 (1 imes 2) 和 (1 imes 1) 的砖来填充矩阵中的 (.),砖只能横着放,问最小代价是多少?
(Solution:)
遍历每一行,算出连续的 (.) 的个数即可。
(Code:)
/*
@Author: nonameless
@Date: 2020-05-29 09:25:29
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
const int N = 1e2 + 10, M = 1e3 + 10;
int n, m, x, y;
char s[N][M];
int main(){
int t; cin >> t;
while(t --){
cin >> n >> m >> x >> y;
for(int i = 1; i <= n; i ++)
scanf("%s", s[i] + 1);
y = min(x + x, y);
int ans = 0;
for(int i = 1; i <= n; i ++){
int cnt = 0;
for(int j = 1; j <= m; j ++){
if(s[i][j] == '.') cnt ++;
else{
ans += cnt / 2 * y + (cnt % 2) * x;
cnt = 0;
}
}
ans += cnt / 2 * y + (cnt % 2) * x;
}
cout << ans << endl;
}
return 0;
}
(C. Mixing Water)
(Description:)
一杯热水的温度是 (h),一杯冷水的温度是 (c),按照热冷热冷热的顺序往桶里倒水,使其平均温度 (tb) 最接近 (t),问最少加几杯水?
(Solution:)
首先要知道的是如果我们加了偶数杯,也就是说热水和冷水各加了 (x) 杯,那么可以得到:(frac{x(h+c)}{2x} = frac{h+c}{2}),所以对于偶数杯的情况,就考虑完了。对于奇数杯,也就是在热冷各加了 (x) 杯后,再加了 (1) 杯热水,也就是说(设 (a = h + c)):
由于 (h > frac{a}{2}),所以 (tb) 是关于 (x) 的递减函数,那么我们就可以二分解决了。
(Code:)
/*
@Author: nonameless
@Date: 2020-05-29 09:38:19
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
int h, c, t;
double calc(int cnt){ // 对于杯数下的平均温度
int a = cnt / 2, b = cnt % 2;
double res = (1ll * a * (h + c) + b * h) * 1.0 / cnt;
return res;
}
int main(){
int test; cin >> test;
while(test --){
cin >> h >> c >> t;
// first 是温度差,second 是杯数,优先按温度差排序
vector<pair<double, int> > vec;
vec.pb({fabs((h + c) / 2.0 - t), 2});
int l = 0, r = 1e9;
int more = 1, less = 1; // 一个大于 t, 一个小于等于 t
while(l <= r){
int mid = l + r >> 1;
int x = 2 * mid + 1; // 这样 x 就一定是奇数了
double tb = calc(x);
if(tb > t){
more = x;
l = mid + 1;
} else{
less = x;
r = mid - 1;
}
}
vec.pb({fabs(t - calc(less)), less});
vec.pb({fabs(t - calc(more)), more});
sort(all(vec)); // 排序
cout << vec[0].y << endl;
}
return 0;
}
(D. Yet Another Yet Another Task)
(Description:)
求某一段区间和减去区间的最大值后的所得得值最大可以是多少?特别得是 (-30 leq a_i leq 30)。
(Solution:)
题目已经明示了我们可以选择区间的最大值得只有 ([1, 30])(如果区间的最大值为负,那么我们为了结果最大,我们只有选长度为 (1) 的区间),所以我们就可以去枚举我们选出的区间的最大值,然后遍历整个数组,只要区间在此处不中断就与结果取 (max)。
(Code:)
/*
@Author: nonameless
@Date: 2020-05-29 14:32:55
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
const int N = 1e5 + 10;
int n, a[N];
int main(){
cin >> n;
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
int ans = 0;
for(int i = 1; i <= 30; i ++){
int tmp = 0; // 连续的和
for(int j = 1; j <= n; j ++){
// 遇到比我们选择的区间最大值还大,就说明他一定不在我们所选的区间中,那么到这里区间就中断了,所以 tmp = 0;
if(a[j] > i) tmp = 0;
else{
tmp = max(0, tmp + a[j]); // 如果到这里区间和为负,那么我们应该舍弃掉
ans = max(ans, tmp - i);
}
}
}
cout << ans << endl;
return 0;
}
(E. Modular Stability)
(Description:)
给定 (n,k),让你构造一个长度为 (k) 的数组 (a),然后将 (a) 数组全排列得到 (k!) 个 (p) 数组,要求对于任意的 (p) 数组和任意一个 (x > 0) 满足:
特别的:(1leq a_1 < a_2 < ... < a_k)。求 (a) 数组的个数?
(Solution:)
要让其任意顺序的模数都相等,那么他们肯定是要满足某种规律的。我就猜测数组 (a) 一定是满足了第一项是后面所有项的因子,这个也很好证明:
设数组 (a) :(d, t_1d, t_2d, t_{k-1}d)。那么 (x) 也可以和 (d) 挂上钩,即 (x = kd + c),对于去模 (a) 数组的结果显然是 (c),对于去模 (p) 数组,遇到比 (x) 大的不会变,比 (x) 小的,那么 (x) 就会逐渐变小,但是 (c) 是始终存在的,直到遇到 (d),变为 (c),而之后的数都比 (c) 大,显然 (c) 就是结果,与模 (a) 数组的结果一致,所以是可行的。
那么我们就可以去枚举 (d),然后算出 ([1, n]) 中 (d) 的倍数的个数,排列组合即可求解。
(Code:)
/*
@Author: nonameless
@Date: 2020-05-29 11:25:26
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
const int mod = 998244353;
const int N = 5e5 + 10;
ll f[N];
ll fPow(ll a, ll b){
ll res = 1;
while(b){
if(b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
ll C(int a, int b){
return f[a] * fPow(f[b] * f[a - b] % mod, mod - 2);
}
int main(){
int n, k;
cin >> n >> k;
f[0] = 1;
for(int i = 1; i <= n; i ++) f[i] = f[i - 1] * i % mod;
ll ans = 0;
for(int i = 1; i <= n; i ++){
int d = n / i - 1;
if(d < k - 1) break;
ans = (ans + C(d, k - 1)) % mod;
}
cout << ans << endl;
return 0;
}