• HDU


    题意:

    从给出的颜料中选出天数个,第一天选一个,第二天选二个...
    例如:第二天从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
    ", sum);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    Word 2003 Excel 2003 的迟绑定(late binding) 方法 时空地图TimeGIS
    快手之友情链接 时空地图TimeGIS
    InfoVista.NET 概述 时空地图TimeGIS
    快手博客 时空地图TimeGIS
    快手文档 www.kuaishou.net 时空地图TimeGIS
    快手之Excel篇 www.kuaishou.net 时空地图TimeGIS
    InfoVista.NET Beta 时空地图TimeGIS
    中国互联网络发展状况统计报告2009年 时空地图TimeGIS
    http://wiki.kuaishou.net 时空地图TimeGIS
    快手影音 www.timegis.com 时空地图TimeGIS
  • 原文地址:https://www.cnblogs.com/somliy/p/9705989.html
Copyright © 2020-2023  润新知