• 2019 杭电多校 第五场


    2019 Multi-University Training Contest 5

    补题链接:2019 Multi-University Training Contest 5

    罚时爆炸 自闭场

    1004 equation (HDU 6627)

    题意:

    给定一个整数 (C)(N)(a_i,b_i),求 (∑_{i=1}^N|a_icdot x + b_i| = C) 的所有解,如果有无穷多个解就输出 -1.

    思路

    分类讨论

    分类讨论去绝对值。根据 (b_i / a_i) 排序,可得各段区间:([-b_0/a_0, ∞), [-b_1/a_1, -b_0/a_0), [-b_2/a_2, -b_1/a_1), ... ,[-b_n/a_n, -b_{n-1}/a_{n-1}), [∞, -b_n/a_n))(suma = sum_{i=1}^Na_i, sumb = sum_{i=1}^Nb_i),依次让 (a_ix+b_i) 变成 (-a_ix-b_i),也就是 (suma - 2a_i, sumb-2b_i),求出 (x_i = frac{c - sumb}{suma}) 并判断是否在区间内。无穷解的情况:(suma = 0, sumb = c)

    感谢杭电没有卡 (double)

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 1e5 + 10;
    
    typedef long long ll;
    
    struct Coefficient {
        ll a, b;
    } co[maxn];
    
    int cmp(Coefficient c1, Coefficient c2) {
        return c1.b * 1.0 / c1.a < c2.b * 1.0 / c2.a;
    }
    
    vector<Coefficient> ans;
    
    ll gcd(ll a, ll b) {
        return b == 0? a: gcd(b, a % b);
    }
    
    int main() {
        int T;
        cin >> T;
        while(T--) {
            ans.clear();
            int n;
            ll c;
            scanf("%d%lld", &n, &c);
            ll suma = 0, sumb = 0;
            for(int i = 1; i <= n; ++i) {
                scanf("%lld%lld", &co[i].a, &co[i].b);
                suma += co[i].a;
                sumb += co[i].b;
            }
            sort(co + 1, co + n + 1, cmp);
            Coefficient t;
            t.a = suma, t.b = sumb;
            if((c - sumb) * 1.0 / suma >= -co[1].b * 1.0 / co[1].a) {
                t.b = c - t.b;
                ans.push_back(t);
            }
    
            int flag = 1;
            for(int i = 1; i <= n; ++i) {
                suma -= co[i].a * 2;
                sumb -= co[i].b * 2;
                t.a = suma;
                t.b = sumb;
                if(!suma) {
                    if(sumb == c) {
                        flag = 0;
                        break;
                    }
                }
                if(i < n) {
                    if((c - sumb) * 1.0 / suma >= -co[i + 1].b * 1.0 / co[i + 1].a && (c - sumb) * 1.0 / suma < -co[i].b * 1.0 / co[i].a) {
                        t.b = c - t.b;
                        ans.push_back(t);
                    }
                } else {
                    if((c - sumb) * 1.0 / suma < -co[i].b * 1.0 / co[i].a) {
                        t.b = c - t.b;
                        ans.push_back(t);
                    }
                }
            }
    
            if(!flag) printf("-1
    ");
            else {
                sort(ans.begin(), ans.end(), cmp);
                printf("%d", ans.size());
                for(int i = 0; i < ans.size(); ++i) {
                    if(ans[i].b * 1.0 / ans[i].a < 0) printf(" -");
                    else printf(" ");
                    ll g = gcd(abs(ans[i].b), abs(ans[i].a));
                    if(ans[i].b == 0) printf("0/1");
                    else printf("%lld/%lld", abs(ans[i].b) / g, abs(ans[i].a) / g);
                }
                printf("
    ");
            }
            
        }
        return 0;
    }
    

    1005 permutation 1 (HDU 6628)

    题意:

    定义排列 (p_1, p_2, ... , p_n) 的 "difference sequence" 为 (p_2-p_1, p_3-p_2,...,p_n-p_{n-1})。现在给定 (N)(K),求长度为 (N) 的所有排列中 "difference sequence" 的字典序第 (K) 小的排列。

    题解:

    暴力 STL 全排列

    题目给定 (K) 的范围不超过 (10^4),而 (8! = 40320 > K),因此可以预处理 (N <= 8) 的情况,当 (N > 8) 时暴力求 (a[1] = n) 的全排列。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 10;
    
    struct P {
        int num[10];
        string str;
    } ans[10][maxn];
    
    int cmp(P p1, P p2) {
        return p1.str < p2.str;
    }
    
    int main() {
        int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
        for(int i = 2; i <= 8; ++i) {
            int cnt = 1;
            do {
                // for(int j = 0; j < i; ++j) {
                //     cout << a[j] << " ";
                // }
                // cout << endl;
                for(int j = 1; j <= i; ++j) {
                    ans[i][cnt].num[j] = a[j];
                    if(j < i) ans[i][cnt].str += a[j + 1] - a[j] + 'A';
                }
                ++cnt;
            } while(next_permutation(a + 1, a + 1 + i));
            sort(ans[i] + 1, ans[i] + cnt, cmp);
            // for(int j = 1; j < cnt; ++j) { for(int k = 1; k <= i; ++k) cout << ans[i][j].num[k] << ""; cout << endl;}
        }
        int T;
        cin >> T;
        while(T--) {
            int n, k;
            scanf("%d%d", &n, &k);
            if(n <= 8) {
                for(int j = 1; j <= n; ++j) {
                    printf("%d", ans[n][k].num[j]);
                    printf("%s", j == n? "
    ": " ");
                }
            } else {
                int a[30];
                a[1] = n;
                for(int i = 2; i <= n; ++i) {
                    a[i] = i - 1;
                }
                for(int i = 0; i < k - 1; ++i) {
                    next_permutation(a + 1, a + 1 + n);
                }
                for(int i = 1; i <= n; ++i) {
                    printf("%d", a[i]);
                    printf("%s", i == n? "
    ": " ");
                }
            }
        }
        return 0;
    }
    

    1006 string matching (HDU 6629)

    题意

    给定字符串 (s[0...len - 1]),对于每个 (i > 0),用下图的程序求 (s[i...len - 1])(s[0...len - 1]) 的最长公共前缀的长度时,字符比较的操作进行了几次?
    title

    题解

    扩展KMP/Z函数

    签到题,扩展KMP (Z函数) 的裸题,cin 被卡了,改成 scanf 就过了。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    char s[1000010];
    
    // Z函数
    vector<int> z_function() {
        int n = strlen(s);
        vector<int> z(n);
        for (int i = 1, l = 0, r = 0; i < n; ++i) {
            if (i <= r)
                z[i] = min(r - i + 1, z[i - l]);
            while (i + z[i] < n && s[z[i]] == s[i + z[i]])
                ++z[i];
            if (i + z[i] - 1 > r)
                l = i, r = i + z[i] - 1;
        }
        return z;
    }
    
    int main() {
        int T;
        scanf("%d",&T);
        while(T--) {
            scanf("%s", s);
            vector<int> v = z_function();
            ll ans = 0;
            int len = v.size();
            for(int i = 1; i < len; ++i) {
                if(i == len - 1) {
                    ans += 1;
                    break;
                }
                if(v[i] + i >= len) ans += v[i]; // while 循环中 i + k >= len 就退出循环了
                else ans += v[i] + 1; // otherwise 语句,多比较一次才退出
            }
            printf("%lld
    ", ans);
        }
    }
    

    1007 permutation 2 (HDU 6630)

    (solved by ch)

    题意

    给定三个正整数 (N, x, y),求 (1 sim N) 的全排列中满足下列条件的个数。

    1. (p_1 = x)
    2. (p_N = y)
    3. 对于所有 (1 le i < N, |p_i - p_{i + 1}|le 2)

    题解

    DP/动态规划

    特殊情况有点多,WA 了好几次。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    const ll mod = 998244353;
    
    const int maxn = 1e5 + 10;
    
    ll dp[maxn] = {1, 1, 2, 3, 4};
    
    int main() {
        for(int i = 5; i < maxn; ++i) {
            dp[i] = (dp[i - 1] + dp[i - 3]) % mod;
            // if(i <= 20)cout << dp[i] << endl;
        }
        int T;
        cin >> T;
        while(T--) {
            ll n, x, y;
            scanf("%lld%lld%lld", &n, &x, &y); // cout << dp[0] << endl;
            // cout << (dp[y - 1] - dp[x] + mod) % mod << endl;
            if(y - x == 1 && n > 3 && x == 1) printf("1
    ");
            else if(y - x == 1 && n > 3 && y == n) printf("1
    ");
            else if(y - x == 1 && n > 3) printf("0
    ");
            else if(n <= 4) printf("%lld
    ", dp[y - x - 1]);
            else if(y - x == 2) printf("1
    ");
            else if(x == 1 && y == n) printf("%lld
    ", dp[y - x - 1]);
            else if(x == 1 || y == n) printf("%lld
    ", dp[y - x - 2]);
            else printf("%lld
    ", dp[y - x - 3]);
        }
        return 0;
    }
    
  • 相关阅读:
    Lab IGMP
    IGMP知识要点
    15、通过例子讲解逻辑地址转换为物理地址的基本过程
    14、一个程序从开始运行到结束的完整过程,你能说出来多少?
    13、进程状态的切换你知道多少?
    12、虚拟技术你了解吗?
    11、动态分区分配算法有哪几种?可以分别说说吗?
    线程池
    10、内存交换和覆盖有什么区别?
    9、如果系统中具有快表后,那么地址的转换过程变成什么样了?
  • 原文地址:https://www.cnblogs.com/wulitaotao/p/11428320.html
Copyright © 2020-2023  润新知