zoukankan      html  css  js  c++  java
  • [题解]牛客挑战赛76题解(施工中)

    A-校园活动

    思路

    了解程度的总和才(9000),直接遍历分组数量,从(n)(1)遍历,一旦能够分组就输出.

    因为(0)对分组数量没有影响,所以只存正整数,方便操作.

    注意全是(0)的情况答案是(n)

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n, sum;
    vector<int> arr;
    
    int check(int num)
    {
        if (sum % num) return 0;
        int tar = sum / num;
        int tmp = 0;
        for (int x : arr)
        {
            if (tmp > tar) return 0;
            if (tmp == tar) tmp = 0; 
            tmp += x;
        }
        return tmp == tar;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n;++i)
        {
            char c;
            scanf(" %c", &c);
            if (c-'0') arr.push_back(c-'0');
            sum += c-'0';
        }
    
        if (sum == 0) 
        {
            printf("%d
    ", n);
        }else{
            int ans = arr.size();
            while (ans > 1)
            {
                if (check(ans)) break;
                ans--;
            }
            if (ans < 2) printf("-1
    ");
            else printf("%d
    ", ans);
        }
    }
    

    C-CG的通关秘籍

    思路

    列出所有情况可以发现一共有(m^n)种.

    当他填第(k, kin[1,n))位数字的时候,这样考虑贡献.

    任何数字在第(k)位上出现的概率都是(frac{1}{m}).

    所以对于每一个数字(p, pin[1,m]), 有(frac{m^n}{m}=m^{n-1})种情况第(k)位是(p).

    在这(m^{n-1})种情况中,任何数字在(k+1)位上出现的概率都是(frac{1}{m}).

    所以对于每一个数字(q,qin[1,m]),有(frac{m^{n-1}}{m}=m^{n-2})种情况第(k)位是(p)并且第(k+1)位是(q).

    考虑每一对可能的(p,q)

    (p<q)的情况有(frac{m*(m-1)}{2}*m^{n-2})种,贡献是(frac{m(m-1)}{2}*m^{n-2})

    (p>q)的情况有(frac{m*(m-1)}{2}*m^{n-2})种,贡献是(frac{2m(m-1)}{2}*m^{n-2})

    所以第(k)位的贡献是(frac{3m(m-1)}{2}*m^{n-2})

    最后一位数字的后面没有东西,所以他没有贡献

    最终答案是(frac{3m(m-1)}{2}*m^{n-2}*(n-1))

    要用快速幂求(m^n-2)(2)的逆元.

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int p = 1e9+7;
    
    int read()
    {
        static char c = 0;
        int ret = 0;
        while (c <'0' || c > '9') c = getchar();
        while ('0' <= c && c <= '9')
        {
            ret = ret * 10 + c -'0';
            c = getchar();
        }
        return ret;
    }
    
    int qpow(int a, int x)
    {
        int ret = 1;
        while (x)
        {
            if (x&1) ret = 1ll * ret * a % p;
            a = 1ll * a * a % p;
            x >>= 1;
        }
        //printf("%d
    ", ret);
        return ret;
    }
    
    int main()
    {
        int t = read();
        while (t--)
        {
            int n = read(), m = read();
            printf("%lld
    ", 3ll * (n-1) % p * qpow(m, n-2) % p 
                                * m % p * (m-1) % p * qpow(2, p-2) % p);
        }
    }
    

    E-牛牛数数

    思路

    题目要求每个(x)只计算一次,每个(x)都是由说给的数字异或产生的.

    给了(10^5)个数字,可以构造一个线性基

    线性基有以下特性

    1. 线性基的元素之间互相异或构造出来的集合,与原本数组的元素之间相互异或构造出来的集合相同,对于本题,这个性质保证不遗漏
    2. 线性基中选择不同的子集,异或出来的数字都是不同的,对于本题,这个性质保证不重复计算
    3. 线性基是满足以上性质的最小集合,通常元素数量不大于数字的二进制位数,对于本题,线性基顶多会有(60)个元素
    4. 线性基各个元素的最高位(1)互不相同

    所以我们先求出线性基.

    然后用一个操作改变线性基,使得满足以下性质

    任意一个元素(x),对于其他所有小于他的元素(y),如果(y)的最高位(1)位于第(p)位,那么(x)的第(p)位一定为(0).

    然后从大到小排序.

    设置一个变量(v=0).

    从大到小遍历线性基的每个元素.

    情况1

    如果线性基的当前元素异或(v)的值大于(K).因为任意一个元素(x),对于其他所有小于他的元素(y),如果(y)的最高位(1)位于第(p)位,那么(x)的第(p)位一定为(0).

    所以之后的值无论如何选择,(v)都会不会变小,所以最终产生的(x)一定大于(K).

    那么当取这个元素之后,后面每个元素都可以取或者不取,对答案的贡献就是(2^{还未被遍历的元素的个数}).

    但是不要直接把这个元素异或(x),因为取这个元素的方案已经考虑完了,之后(v)都是不带这个元素的.

    情况2

    如果线性基的当前元素异或(v)的值小于(K).那么不取这一个元素的情况一定不会有贡献.

    因为后面的元素的(1)的最高位不会高过这一个元素,所以不取这一个元素的话,后面怎么取叶不会比(K)大.

    取了这个元素的情况下有没有贡献我们还不知道,要到考虑后面的元素才能知道,这里先把这个元素异或(v).

    代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    long long read()
    {
        static char c = 0;
        long long ret = 0;
        while (c <'0' || c > '9') c = getchar();
        while ('0' <= c && c <= '9')
        {
            ret = ret * 10 + c -'0';
            c = getchar();
        }
        return ret;
    }
    
    
    
    int main()
    {
        int n = read();
        long long K = read();
        long long ans = 0, v = 0;
        vector<long long> base;
        for (int i = 1; i <= n; ++i)
        {
            long long x = read();
            for (long long y : base) x = min(x, x^y);
            if (x) base.push_back(x);
        }
    
        for(int i = 0; i < base.size(); i++)
            for(int j = 0; j < base.size(); j++)
                if(i != j)
                    base[i] = min(base[i], base[i] ^ base[j]);
    
        sort(base.begin(), base.end(), greater<long long>());
        //for (long long x : base) printf("%lld
    ", x);
        for (int j = 0; j < base.size(); ++j)
        {
            if ((v ^ base[j]) > K)
                ans += 1ll << (base.size() - j - 1);
            else
                v ^= base[j];
        }
        printf("%lld
    ", ans);
    }
    
  • 相关阅读:
    python虚拟环境使用
    虚拟化网络进阶管理
    虚拟化进阶管理
    KVM虚拟化
    Xen虚拟化
    Virtualization基础
    Virnish使用
    CentOS配置FTP服务器
    Ajax结合Json进行交互数据(四)
    将 数据库中的结果集转换为json格式(三)
  • 原文地址:https://www.cnblogs.com/zzidun-pavo/p/14288885.html
Copyright © 2011-2022 走看看