2019 Multi-University Training Contest 8
补题链接:2019 Multi-University Training Contest 8
1003 Acesrc and Good Numbers HDU 6659
题意
定义 (f(d, n)) 为十进制下 (1) 到 (n) 所有数的数位中数字 (d) 出现的次数。给定 (x),找出最大的 (n(n le x)) 满足 (f(d, n) = n)。
题解
看到了一个神仙做法。
显然如果 (f(d, x) = x) 时就直接输出。
否则,需要缩小 (x)。令 (f(d, x) = y),则需要将 (x) 缩小 (lceil frac{|x - y|}{18} ceil)。即 (x = x - abs(f(d, x) - x) / 18)。原因是 (f(d, x)) 与 (f(d, x - 1)) 最多相差 (18) 个 (d) ( (e.g. f(9, 10^{18}-1) to f(9, 10^{18}-2)))。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// 计算 1 到 n 中数字 x 出现的次数
ll f(ll d, ll n) {
ll cnt = 0, k;
for (ll i = 1; k = n / i; i *= 10) {
cnt += (k / 10) * i;
int cur = k % 10;
if (cur > d) {
cnt += i;
}
else if (cur == d) {
cnt += n - k * i + 1;
}
}
return cnt;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) {
ll d, x;
cin >> d >> x;
while (true) {
ll num = f(d, x);
if (num == x) {
cout << x << endl;
break;
} else {
x -= max(1LL, abs(num - x) / 18);
}
}
}
return 0;
}
参考
2019 Multi-University Training Contest 8——Acesrc and Good Numbers(数学 想法)
1009 Calabash and Landlord HDU 6665
题意:
给出两个矩形,求矩形把平面分割成几块。
思路
分类讨论
听说只要离散化到 (5*5) 的格子里然后 (DFS) 就可以了,有空再补。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f;
struct Point
{
ll x, y;
}p[10];
int main() {
int T;
cin >> T;
while (T--) {
ll maxx = 0, maxy = 0, minx = inf, miny = inf;
for(int i = 1; i <= 2; ++i) {
scanf("%lld%lld", &p[i].x, &p[i].y);
}
p[3].x = p[1].x;
p[3].y = p[2].y;
p[4].x = p[2].x;
p[4].y = p[1].y;
ll s1 = (p[2].x - p[1].x) * (p[2].y - p[1].y);
for(int i = 5; i <= 6; ++i) {
scanf("%lld%lld", &p[i].x, &p[i].y);
}
p[7].x = p[5].x;
p[7].y = p[6].y;
p[8].x = p[6].x;
p[8].y = p[5].y;
ll s2 = (p[6].x - p[5].x) * (p[6].y - p[5].y);
for(int i = 1; i <= 8; ++i) {
maxx = max(maxx, p[i].x);
maxy = max(maxy, p[i].y);
minx = min(minx, p[i].x);
miny = min(miny, p[i].y);
}
// for(int i = 1; i <= 8; ++i) {
// cout << p[i].x << " " << p[i].y << endl;
// }
if(p[1].x == p[5].x && p[1].y == p[5].y && p[3].x == p[7].x && p[3].y == p[7].y && p[6].x == p[2].x && p[6].y == p[2].y && p[4].x == p[8].x && p[4].y == p[8].y) {
printf("2
");
continue;
}
ll s = (maxx - minx) * (maxy - miny); // cout << s << endl;
if(s1 == s || s2 == s) {
if((p[1].x == p[5].x && p[2].x == p[6].x)) {
if(p[5].y == p[1].y || p[6].y == p[2].y) printf("3
");
else printf("4
");
} else if((p[1].y == p[5].y && p[2].y == p[6].y)) {
if(p[5].x == p[1].x || p[6].x == p[2].x) printf("3
");
else printf("4
");
}
else printf("3
");
} else if(p[4].y >= p[7].y || p[8].y >= p[3].y || p[5].x >= p[2].x || p[1].x >= p[6].x) {
printf("3
");
} else if((p[2].x - p[1].x) * (p[6].y - p[5].y) == s) {
if(p[6].y > p[2].y && p[5].y < p[1].y && p[1].x < p[5].x && p[2].x > p[6].x) {
printf("6
");
} else if(p[1].x == p[5].x && p[1].y == p[5].y) {
printf("4
");
} else if(p[3].x == p[7].x && p[3].y == p[7].y) {
printf("4
");
} else if(p[2].x == p[6].x && p[2].y == p[6].y) {
printf("4
");
} else if(p[4].x == p[8].x && p[4].y == p[8].y) {
printf("4
");
} else {
printf("5
");
}
} else if((p[6].x - p[5].x) * (p[2].y - p[1].y) == s) {
if(p[2].y > p[6].y && p[1].y < p[5].y && p[5].x < p[1].x && p[6].x > p[2].x) {
printf("6
");
} else if(p[1].x == p[5].x && p[1].y == p[5].y) {
printf("4
");
} else if(p[3].x == p[7].x && p[3].y == p[7].y) {
// cout << 1 << endl;
printf("4
");
} else if(p[2].x == p[6].x && p[2].y == p[6].y) {
printf("4
");
} else if(p[4].x == p[8].x && p[4].y == p[8].y) {
printf("4
");
} else {
printf("5
");
}
} else {
printf("4
");
}
}
return 0;
}
1010 Quailty and CCPC HDU 6666
签到题。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
struct Team
{
char name[20];
ll p, t;
} te[maxn];
int cmp(Team t1, Team t2) {
if(t1.p == t2.p) return t1.t < t2.t;
return t1.p > t2.p;
}
int main() {
int T;
cin >> T;
while(T--) {
int n;
int d;
scanf("%d%d", &n, &d);
for(int i = 0; i < n; ++i) {
scanf("%s%lld%lld", &te[i].name, &te[i].p, &te[i].t);
}
sort(te, te + n, cmp);
// d *= 0.1;
// double l = floor(d * n), r = ceil(d * n);
// double de = d * n - floor(d * n);
if((d * n) % 10 == 5) {
int ans = d * n / 10;
printf("%s
", te[ans].name);
} else {
printf("Quailty is very great
");
}
}
return 0;
}
1011 Roundgod and Milk Tea HDU 6667
题意:
有 (n) 个班级,每个班有 (a_i) 个人,做了 (b_i) 杯奶茶,每个班的每个人最多喝一杯奶茶且不能和自己班做的奶茶,问最多共有多少人喝到奶茶。
思路
最初的想法是用一个 (sum) 记录所有剩余的奶茶数,然后每个组能喝的奶茶数为 (sum -) 该组的奶茶(自己不能喝自己的) (+) 上一组做的奶茶 (上一组减掉的加回来)。后来发现有点问题,就是中间一步减掉自己的奶茶可能是减多的,也就是上一组喝掉的可能就是当前组的奶茶,那么当前组剩余的奶茶是比原来少的,于是就用 (tmp2) 保存上一组喝掉的奶茶数,每次让上一组喝掉当前组的奶茶,如果不够喝再用 (tmp) 保存还要喝掉的奶茶数,往下迭代。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
struct Team
{
ll m, n; // 人数 奶茶数
} t[maxn];
int cmp(Team t1, Team t2) {
return t1.m > t2.m;
}
int main() {
int T;
cin >> T;
while(T--) {
int n;
scanf("%d", &n);
ll sum = 0;
for(int i = 0; i < n; ++i) {
scanf("%lld%lld", &t[i].m, &t[i].n);
sum += t[i].n;
}
sort(t, t + n, cmp);
ll ans = 0;
ll tmp = t[0].n; // tmp 保存喝掉的奶茶数 第一组一定要被喝
ll tmp2 = 0; // tmp2 保存的是上一组喝掉的奶茶
for(int i = 0; i < n; ++i) {
if(i) {
// 上一组喝掉的奶茶数+之前喝掉的奶茶数
if(t[i].n < tmp2 + tmp) {
t[i].n = 0;
tmp = tmp2 + tmp - t[i].n;
} else {
t[i].n = t[i].n - (tmp2 + tmp);
tmp = 0;
}
}
sum -= t[i].n; // 自己不能喝自己的奶茶
if(i) sum += t[i - 1].n; // 可以喝上一组的奶茶
// 剩余的奶茶数与第 i 组人数比较
if(sum >= t[i].m) {
ans += t[i].m;
sum -= t[i].m;
tmp2 = t[i].m;
} else {
ans += sum;
sum -= sum;
tmp2 = sum;
}
// cout << ans << endl;
}
printf("%lld
", ans);
}
return 0;
}
比赛中完全想复杂了,其实完全可以很快处理。把每个人能喝的奶茶加起来和所有的奶茶比较即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
ll a[maxn], b[maxn];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
ll sum = 0;
for(int i = 0; i < n; ++i) {
scanf("%lld%lld", &a[i], &b[i]);
sum += b[i];
}
ll ans = 0;
for(int i = 0; i < n; ++i) {
ans += min(a[i], sum - b[i]);
}
printf("%lld
", min(ans, sum));
}
return 0;
}