思路

了解程度的总和才\(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", n);
    }else{
        int ans = arr.size();
        while (ans > 1)
        {
            if (check(ans)) break;
            ans--;
        }
        if (ans < 2) printf("-1\n");
        else printf("%d\n", ans);
    }
}

C-CG的通关秘籍

思路

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

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

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

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

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

所以对于每一个数字\(q,q\in[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\n", ret);
    return ret;
}

int main()
{
    int t = read();
    while (t--)
    {
        int n = read(), m = read();
        printf("%lld\n", 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\n", 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\n", ans);
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-27
  • 2021-12-13
  • 2021-08-07
  • 2021-07-21
  • 2021-11-21
  • 2021-08-21
猜你喜欢
  • 2021-10-01
  • 2022-12-23
  • 2021-08-26
  • 2021-12-18
  • 2022-03-08
  • 2022-12-23
相关资源
相似解决方案