A. Sequence with Digits
\(Description:\)
定义: \(a_{n + 1} = a_n + minDigit(a_n) \times maxDigit(a_n)\)。
给定 \(a_1\) 和 \(k\),求 \(a_k\) ?
\(Solution:\)
显然当 \(a_n\) 中包含了 \(0\) 时,之后的数都等于 \(a_n\)。那么我们就要判断是否一定会出现包含 \(0\) 的情况,并且复杂度是可以接受的。
首先 \(minDigit(x) \times maxDigit(x) \leq 81\)。那么令 \(t = x\ mod\ 1000\),那么 \(t < 1000\),那么在经过递增过后,一定会出现 \(t + m \geq 1000\),由于 \(m \leq 81\),那么 \(t + m < 1100\),也就是一千零几,那么他的百位一定是 \(0\)。所以我们是可以直接循环去解决。
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
ll calc(ll num){
ll Min = 9, Max = 0;
while(num){
Min = min(Min, num % 10);
Max = max(Max, num % 10);
num /= 10;
}
return Min * Max;
}
int main(){
int t; cin >> t;
while(t --){
ll a, k;
cin >> a >> k;
for(int i = 2; i <= k; i ++){
a = a + calc(a);
if(calc(a) == 0) break;
}
cout << a << endl;
}
return 0;
}
B. Young Explorers
\(Description:\)
给定长度为 \(n\) 的数组 \(e\),进行分组,要求 \(e_i \leq\) 该组的人数,问最多分几组?
\(Solution:\)
从小到大排个序,从左边到右边遍历一遍,能组成一组就组成一组。
\(Code:\)
//http://codeforces.com/contest/1355/problem/B
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI = acos(-1.0);
const double eps = 1e-8;
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 = 3e5 + 10;
int e[N];
int main(){
int t; cin >> t;
while(t --){
int n; cin >> n;
for(int i = 1; i <= n; i ++)
scanf("%d", &e[i]);
sort(e + 1, e + n + 1);
int ans = 0;
int cnt = 0; // 记录当前组的人数
for(int i = 1; i <= n; i ++){
cnt ++;
if(e[i] <= cnt){ // 符合要求了
cnt = 0;
ans ++;
}
}
cout << ans << endl;
}
return 0;
}
C. Count Triangles
\(Description:\)
给定 \(a,\ b,\ c,\ d\),问有多少组 \((x,\ y,\ z)\) 构成三角形,要求满足:\(a\leq x\leq b\leq y\leq c\leq z\leq d\) 。
\(Solution:\)
枚举 \(x\),由于 \(x + y > z\) 并且 \(z \geq c\),那么 \(y_{min} = max(b,\ c - x + 1)\) 才能符合要求;当 \(x + y > d\) 之后,\(z\) 的选择始终为 \(d - c + 1\) 个,那么我们计算出 \(y_{max} = max(b,\ d - x + 1)\)。那么我们就可以分两段计算:\([y_{min},\ y_{max} - 1]\) 和 \([y_{max}, c]\)。
对于 \([y_{min}, y_{max} - 1]\):\(\sum_{i = y_{min}}^{y_{max}-1}\ (x + y_i - c)\),\((x + y_i - c)\) 就是 \(z\) 可以选择的个数。而这显然是等差数列求和。
对于 \([y_{max}, c]\):\((c - y_{max} + 1) \times (d - c + 1)\)。
\(Code:\)
//http://codeforces.com/contest/1355/problem/C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI = acos(-1.0);
const double eps = 1e-8;
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(){
// a <= x <= b <= y <= c <= z <= d
ll a, b, c, d;
cin >> a >> b >> c >> d;
ll ans = 0;
for(ll x = a; x <= b; x ++){
ll yMin = max(b, c - x + 1);
ll yMax = max(b, d - x + 1);
ans += max(c - yMax + 1, 1ll * 0) * (d - c + 1); // 有可能 yMax > c
yMax = min(yMax - 1, c);
ans += (yMax - yMin + 1) * (2 * (x - c) + yMin + yMax) / 2;
}
cout << ans << endl;
return 0;
}
D. Game With Array
\(Description:\)
能否构造出一个数组,使得数组中任意一段区间的和不为 \(k\) 和 \(s - k\)?\(s\) 为数组的和。( \(k\) 自选)
\(Solution:\)
对于 \(n = 1\) 的情况很容易判断。
对于 \(n \geq 2\):构造出不含 \(1\) 的数组,令 \(k = 1\) 即可符合要求。那么也就是数组每一项最少为 \(2\),也就是说 \(s \leq 2 \times n - 1\) 的不行。
\(Code:\)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI = acos(-1.0);
const double eps = 1e-8;
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 n, s;
cin >> n >> s;
if(n == 1){
if(s == 1) puts("NO");
else{
puts("YES");
cout << s << endl;
cout << s - 1 << endl;
}
}else{
if(s <= 2 * n - 1) puts("NO");
else{
puts("YES");
for(int i = 1; i < n; i ++)
printf("2 ");
cout << s - 2 * (n - 1) << endl;
cout << 1 << endl;
}
}
return 0;
}
E. Restorer Distance
\(Description:\)
给出长度为 \(n\) 的数组 \(h\),要求使数组中的数都相同。
有三种操作:
\(1.\) 使某个数加 \(1\),花费 \(a\);
\(2.\) 使某个数减 \(1\),花费 \(r\);
\(3.\) 选择两个数,一个加 \(1\),一个减 \(1\),花费 \(m\)。
求最少代价?
\(Solution:\)
我们枚举最终的高度,可以想到的是代价一定是随高度变化的一个二次函数。那么直接三分就可以轻易求解。
\(Code:\)
//http://codeforces.com/contest/1355/problem/E
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
const double PI = acos(-1.0);
const double eps = 1e-8;
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, r, m;
int h[N];
ll sum[N];
ll check(int mid){
ll more = 0, less = 0;
for(int i = 1; i <= n; i ++){
if(h[i] < mid) less += mid - h[i];
if(h[i] > mid) more += h[i]- mid;
}
ll res = min(less, more) * m;
if(less > more) res += a * (less - more);
else res += r * (more - less);
return res;
}
int main(){
cin >> n >> a >> r >> m;
for(int i = 1; i <= n; i ++)
scanf("%d", &h[i]);
sort(h + 1, h + n + 1);
m = min(m, a + r);
int le = h[1], ri = h[n];
ll ans = LNF;
while(le <= ri){
int lmid = le + (ri - le) / 3;
int rmid = ri - (ri - le) / 3;
ll costl = check(lmid);
ll costr = check(rmid);
if(costl < costr){
ans = costl;
ri = rmid - 1;
}else{
ans = costr;
le = lmid + 1;
}
}
cout << ans << endl;
return 0;
}