• 牛客编程巅峰赛S1第3场


    牛客编程巅峰赛S1第3场 - 青铜&白银

    A-[位数求和]

    思路:

    直接按照枚举([10^n,10^{n+1}-1])种的每个数,$O(log_{10}(x))判断每位上的数字之和为m即可。

    代码:
    class Solution {
    public:
        /**
         * 返回这样的数之和
         * @param n int整型 数的长度
         * @param m int整型 各个为之和
         * @return long长整型
         */
        long long sum(int n, int m) {
            // write code here
           int base = 1;
            for (int i = 1; i <= n - 1; ++i)
            {
                base *= 10;
            }
            int up = base * 10 - 1;
            long long ans = 0;
            for (int i = base; i <= up; ++i)
            {
                int num = i;
                int cnt = 0;
                while (num > 0)
                {
                    cnt += num % 10;
                    num /= 10;
                }
                if (cnt == m)
                {
                    ans += i;
                }
            }
            return ans;
        }
    };
    

    B-不可思议

    思路:

    仔细观察生成的树的随机代码:

    seed4 = (seed1 + seed2) % 998244353 * seed3 % 998244353;
            u[i] = i + 1;
            v[i] = (seed4 % i) + 1;
    

    每一个边都是一个新节点和之前已经出现的节点连边。

    这样生成的树高度的期望值是(O(log_2(n))),所以先预处理每一个节点的父节点后,

    对于每一个询问可以直接暴力求即可。

    代码:
    class Solution {
    public:
        /**
         * 
         * @param n int整型 
         * @param seed1 long长整型 
         * @param seed2 long长整型 
         * @param seed3 long长整型 
         * @param x int整型 
         * @return long长整型
         */
        int u[100010], v[100010];
    std::vector<int> e[100010];
    void get_tree(long long seed1 , long long seed2, long long seed3, int n)
    {
        long long seed4;
        for (int i = 1; i <= n - 1; ++i)
        {
            seed4 = (seed1 + seed2) % 998244353 * seed3 % 998244353;
            u[i] = i + 1;
            v[i] = (seed4 % i) + 1;
            seed3 = seed2;
            seed2 = seed1;
            seed1 = seed4;
        }
    }
    int far[100010];
    void dfs(int x, int pre)
    {
        far[x] = pre;
        for (auto &y : e[x])
        {
            if (y != pre)
            {
                dfs(y, x);
            }
        }
    
    }
    int ans(int x, int y)
    {
        int res = 0;
        while (1)
        {
            res += ((y + 2 * x) ^ (y + x));
            if (x == 1)
            {
                break;
            } else
            {
                x = far[x];
            }
        }
        return res;
    }
    long long work(int n, long long seed1, long long seed2, long long seed3, int x) {
        // write code here
        get_tree(seed1,  seed2,  seed3, n);
        for (int i = 1; i < n; ++i)
        {
            e[v[i]].push_back(u[i]);
            e[u[i]].push_back(v[i]);
        }
        dfs(1, 0);
        int lastans = 0;
        int ret = 0;
        int y = 0;
        int z;
        for (int i = 1; i <= n; ++i)
        {
            z = ans(x, y);
            ret = (ret + z) % 998244353;
            lastans = z;
            x = ((x + lastans)^ret) % n + 1;
            y = lastans;
        }
        return ret;
    }
    };
    

    C-牛牛晾衣服

    思路:

    二分(mid)代表要多少时间可以把衣服全烘干,显然具有单调性((mid)可以烘干的话,(mid+1)一定可以。)

    然后对于每一个衣服(a_i),找到最小的(x)使其(a_i-x*k-(mid-x)<=0),然后如果可以找到且(xin[0,mid]),以及(mathit x)的总和(sumle mid)

    代码:
    class Solution {
    public:
        int C(int x, int y)
        {
            return (x + y - 1) / y;
        }
        bool check(int mid,  vector<int>& a, int k)
        {
            int n = a.size();
            int cnt = 0;
            if (mid >= a[0])
                return 1;
            for (int i = 0; i < n; ++i)
            {
                if (mid * k < a[i])
                    return 0;
    
                int x = C(max(a[i] - mid, 0), k - 1);
                if (x < 0 || x > mid)
                {
                    return 0;
                }
                cnt += x;
            }
            return cnt <= mid;
        }
        int solve(int n, vector<int>& a, int k) {
            // write code here
            sort(a.begin(), a.end(), greater<int>());
            int l = 1;
            int r = 1000000000;
            int mid;
            int ans ;
            while (l <= r)
            {
                mid = (l + r) >> 1;
                if (check(mid, a, k))
                {
                    ans = mid;
                    r = mid - 1;
                } else
                {
                    l = mid + 1;
                }
            }
            return ans;
        }
    };
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    深入研究Node.js的底层原理和高级使用
    Node.js实际案例分享
    Node.js的下载、安装、配置、Hello World、文档阅读
    Node.js初识
    sphinx初识
    Yii2中后台用前台的代码设置验证码显示不出来?
    彻底解决Yii2中网页刷新时验证码不刷新的问题
    yii2高级模板使用一个域名管理前后台
    Shot(三分)
    遮挡判断(模拟)
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/13326317.html
Copyright © 2020-2023  润新知