A. Sequence with Digits
(Description:)
定义: (a_{n + 1} = a_n + minDigit(a_n) imes maxDigit(a_n))。
给定 (a_1) 和 (k),求 (a_k) ?
(Solution:)
显然当 (a_n) 中包含了 (0) 时,之后的数都等于 (a_n)。那么我们就要判断是否一定会出现包含 (0) 的情况,并且复杂度是可以接受的。
首先 (minDigit(x) imes 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)) 构成三角形,要求满足:(aleq xleq bleq yleq cleq zleq 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) imes (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 imes 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;
}