HDU - 4810 - Wall Painting (位运算 + 数学)

题意:

从给出的颜料中选出天数个,第一天选一个,第二天选二个...
例如:第二天从4个中选出两个,把这两个进行异或运算(xor)计入结果
对于每一天输出所有异或的和
$\sum_{i=1}^nC_{n}^{i}$

思路:

0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1)
例如样例
4
1 2 10 1
这4个数的二进制表示分别为:
0 0 0 1
0 0 1 0
1 0 1 0
0 0 0 1
第一天: 分别选出 1, 2, 10 ,1 = 14
第二天: 从4个中选出2个进行异或运算,如果选出的是两个1,那么异或是没有意义的,因为 1⊕1=0
转换为2进制进行计算,对于每一列选出奇数个1,这样可以保证异或有意义,所以我们只需要记录每一位有多少个1

从4个中选出2个来做异或,第4位上只有1个1,所以有3种选法可以使得这一位异或之后结果为1,(也就是$C_{3}^{1}$ * $C_{1}^{1}$),第3位的没有1,所以异或结果一定为0,第2位上又2个1,所以有4种选法,同理第一位上也是4种。
具体看代码中解释

代码:

#include<iostream>
#include <cstring>
#include <cmath>

using namespace std;

typedef long long LL;
const int maxn = 1000 + 10;
const int mod = 1e6 + 3;
LL c[maxn][maxn];
LL a[100];

LL pow_num(int a, int n) {//快速幂
    if (a == 0) return 0;
    int ans = 1;
    while (n) {
        if (n & 1) ans *= a;
        n >>= 1;
        a *= a;
    }
    return ans;
}


void deal(LL x) {
    int i = 0;
    while (x) {
        if (x & 1)
            a[i]++;
        i++;
        x >>= 1;
    }
}

void init() {
    for (int i = 0; i < maxn; i++)
        c[i][0] = c[i][i] = 1;
    for (int i = 2; i < maxn; i++)
        for (int j = 1; j < i; j++)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}

int main() {
    int t;
    init();//组合数打表
    while (~scanf("%d", &t)) {
        memset(a, 0, sizeof(a));
        for (int i = 1; i <= t; i++) {
            LL x;
            scanf("%lld", &x);
            deal(x);//储存每一位二进制中1的数量
        }
        for (int i = 1; i <= t; i++) {//枚举每一天
            LL sum = 0;
            for (int j = 0; j < 32; j++) {//枚举二进制每一位
                LL ans = 0;
                for (int l = 1; l <= i; l += 2)//选出奇数个1,每次自增2
                    ans = (ans + c[a[j]][l] * c[t - a[j]][i - l] % mod) % mod;
                    //这里是从a[j]个1中选出l个 × 从a[j]个0中选出i-l个
                sum = (sum + ans * pow_num(2, j)) % mod;
                //乘上每一位对应的10进制大小,所有的加起来就是这一天所求的
            }
            if (i != t)
                printf("%lld ", sum);
            else printf("%lld\n", sum);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/somliy/p/9705989.html