2019 杭电多校 第八场

Posted wulitaotao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 杭电多校 第八场相关的知识,希望对你有一定的参考价值。

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 \rceil\)。即 \(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\n");
            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\n");
                else printf("4\n");
             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\n");
                else printf("4\n");
            
            else printf("3\n");
         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\n");
         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\n");
             else if(p[1].x == p[5].x && p[1].y == p[5].y) 
                printf("4\n");
             else if(p[3].x == p[7].x && p[3].y == p[7].y) 
                printf("4\n");
             else if(p[2].x == p[6].x && p[2].y == p[6].y) 
                printf("4\n");
             else if(p[4].x == p[8].x && p[4].y == p[8].y) 
                printf("4\n");
             else 
                printf("5\n");
            
         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\n");
             else if(p[1].x == p[5].x && p[1].y == p[5].y) 
                printf("4\n");
             else if(p[3].x == p[7].x && p[3].y == p[7].y) 
                // cout << 1 << endl;
                printf("4\n");
             else if(p[2].x == p[6].x && p[2].y == p[6].y) 
                printf("4\n");
             else if(p[4].x == p[8].x && p[4].y == p[8].y) 
                printf("4\n");
             else 
                printf("5\n");
            
         else 
            printf("4\n");
        
    
    
    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\n", te[ans].name);
         else 
            printf("Quailty is very great\n");
        
    
    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\n", 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\n", min(ans, sum));
    
    return 0;

以上是关于2019 杭电多校 第八场的主要内容,如果未能解决你的问题,请参考以下文章

2019杭电多校第九场

2019 杭电多校 第二场

2019 杭电多校 第四场

2019 杭电多校 第九场

2019 杭电多校 第六场

2019 杭电多校 第一场