• FJNU 1153 Fat Brother And XOR(胖哥与异或)


    FJNU 1153 Fat Brother And XOR(胖哥与异或)

    Time Limit: 1000MS   Memory Limit: 257792K

    【Description】

    【题目描述】

    Fat brother had master ACM, recently he began to study the operation of XOR (the operation “^”). He thought of a very interesting question: select arbitrary k positive integers from the n positive integers, then XOR the selected k digital, sum all cases of XOR. Now he wants to quickly calculate the results. Maybe the results will be great, just modulo 20162333.

    For example, 3 integers: 1 2 3, select arbitrary 2 positive integers, the all cases:

    {1,2}, {2, 3}, {1, 3}. So the results is {(1 ^ 2) + (2 ^ 3) + (1 ^ 3)} %20162333

    胖哥是个ACM大牛,最近他在学习异或操作(运算符为“^”)。他想到了个有趣的问题:从n个正整数中任选k个,然后对这k个数异或,对所有异或的结果求和。现在他想快速计算结果。最终结果可能很大,于是模20162333。

    例如,3个整数:1 2 3,选择任意2个正整数,所有情况为:

    {1,2}, {2, 3}, {1, 3}。因此结果为{(1 ^ 2) + (2 ^ 3) + (1 ^ 3)} %20162333

    【Input】

    【输入】

    There are multiple test cases. The first line of input contains an integer T (T <= 20) indicating the number of test cases. For each test case:

    The first line contains two integer n, k (1 <= k <= n <= 1000)

    The second line contains n integer ai (1 <= ai <= 1000000000)

    多组测试用例。

    第一行是一个整数T(T <= 20)表示测试用例的数量。对于每个测试用例:

    第一行有两个整数,k(1 <= k <= n <= 1000)

    第二行有n个整数ai(1 <= ai <= 1000000000)

    【Output】

    【输出】

    For each test case, output the sum % 20162333

    对于每个测试用例,输出和%20162333

    【Sample Input - 输入样例】

    【Sample Output - 输出样例】

    2

    3 2

    1 2 3

    6 2

    6 6 6 6 6 6

    6

    0

    【Hint】

    【提示】

    The

    first sample test case: (1 ^ 2) + (2 ^ 3) + (1 ^ 3) = 6

    The

    second sample test case: (6 ^ 6) * 15 = 0

    第一个样例:

    (1 ^ 2) + (2 ^ 3) + (1 ^ 3) = 6

    第二个样例:

    (6 ^ 6) * 15 = 0

    【题解】

    这道题需要以二进制的观点来看待每个ai

    举个例子:

    Xai表示二进制的下ai的第X位(为方便表示从0开始)

    (a1 ^ a2) + (a2 ^ a3) + (a1 ^ a3)

    =[(0a1 ^ 0a2) + (0a2 ^ 0a3) + (0a1 ^ 0a3)]*20 +

    [(1a1 ^ 1a2) + (1a2 ^ 1a3) + (1a1 ^ 1a3)]*21 +

    [(2a1 ^ 2a2) + (2a2 ^ 2a3) + (2a1 ^ 2a3)]*22 +

    …………………………………………………………………………… +

    [(Xa1 ^ Xa2) + (Xa2 ^ Xa3) + (Xa1 ^ Xa3)]*2X

    此时只剩0和1了

    我们可以很轻易地知道:0 ^ 0 = 0, 1 ^ 0 = 1, 1 ^ 1 = 0

    当然了,a ^ b = b ^ a

    所以除了1 ^ 0之外,其他结果为0的情况都是无用的。

    因此,题目转换为:求二进制下,1 ^ 0 这种情况出现的次数。

    统计ai中二进制第X位出现几次1,保存到bit[x]

    第X位提供的1 = 2X * 有效情况数

    有效情况数就是由bit[X]个1与 n-bit[X]个0组合出来的

    并且只有取奇数个1的时候,异或的结果才能为1(1 ^ 1 = 0)

    由此可以得出

    当前有效情况数: 

    最后利用递推公式快速求组合数c(n,m)=c(n-1,m-1)+c(n-1,m)

    (当然你把这个公式当成杨辉三角也是可以的:))

    【代码 C++】

     1 #include<cstdio>
     2 #include <cstring>
     3 #define  mx 1005
     4 #define mod 20162333
     5 int main(){
     6     int t, n, k, i, j, w, opt, bit[30], c[mx][mx];
     7     for (i = 0; i < mx; ++i){
     8         for (c[i][0] = c[i][i] = j = 1; j < i; ++j)
     9             c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
    10     }
    11     while (~scanf("%d", &t)){
    12         while (t--){
    13             memset(bit, 0, sizeof(bit));
    14             scanf("%d%d", &n, &k);
    15             for (i = 0; i < n; ++i){
    16                 scanf("%d", &j);
    17                 for (w = 0; j; j >>= 1) bit[w++] += j & 1;
    18             }
    19             for (i = opt = 0; i < 30; ++i){
    20                 for (j = 1; j <= k; j += 2){
    21                     opt += (1LL << i) *c[bit[i]][j] % mod*c[n - bit[i]][k - j] % mod;
    22                     opt %= mod;
    23                 }
    24             }
    25             printf("%d
    ", opt);
    26         }
    27     }
    28     return 0;
    29 }
     1 #include<cstdio>
     2 #include <cstring>
     3 #define  mx 1005
     4 #define mod 20162333
     5 int read_int(){
     6     int add = getchar() - '0';
     7     int a = getchar();
     8     while (a >= '0' && a <= '9') add = add * 10 + a - '0', a = getchar();
     9     return add;
    10 }
    11 int main(){
    12     int t, n, k, i, j, w, opt, bit[30], *c[mx];
    13     for (i = 0; i < mx; ++i){
    14         c[i] = new int[i + 1];
    15         for (c[i][0] = c[i][i] = j = 1; j < i; ++j)
    16             c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
    17     }
    18     while (t = read_int(), t>0){
    19         while (t--){
    20             memset(bit, 0, sizeof(bit));
    21             n = read_int(); k = read_int();
    22             for (i = 0; i < n; ++i){
    23                 for (w = 0, j = read_int(); j; j >>= 1) bit[w++] += j & 1;
    24             }
    25             for (i = opt = 0; i < 30; ++i){
    26                 for (j = 1; j <= k; j += 2){
    27                     if (bit[i] < j || n - bit[i] < k - j) continue;
    28                     opt += (1LL << i) *c[bit[i]][j] % mod*c[n - bit[i]][k - j] % mod;
    29                     opt %= mod;
    30                 }
    31             }
    32             printf("%d
    ", opt);
    33         }
    34     }
    35     return 0;
    36 }
    伪·优化


     

  • 相关阅读:
    JavaScript WebSocket C# SuperSocket.WebSocket 示例
    Nginx 配置
    Temporary Post Used For Theme Detection (272f6d70fb8946f3a568afd3d7b053bd 3bfe001a32de4114a6b44005b770f6d7)
    SpringBoot多数据源事务解决方案
    SpringBoot集成mybatis拦截器修改表名
    点击各个按钮,在执行操作之前出现确认提示框
    incoming change和current change
    Expected Number with value 8, got String with value "8".
    正则只能输入数字遇到的问题
    Antd 4.19 Modal + Form;打开modal时使用setFieldsValue,首次回显正常,第二次无效?
  • 原文地址:https://www.cnblogs.com/Simon-X/p/5426192.html
Copyright © 2020-2023  润新知