zoukankan      html  css  js  c++  java
  • ZZUOJ 10509: xor运算统计

    题目链接http://acm.zzu.edu.cn:8000/problem.php?id=10509

    题目大意:给定n个正整数,a1 a2 ... an,从中选取k个数 , ai1 ai2 ai3 ... Aik,其中(1<=i1<i2<i3<...<ik<=n),u=ai1 ^ai2 ^ai3 ^... ^Aik,将异或和为u 的序列(i1,i2,...,ik)的个数记为f(u),求∑(f(u)*u) (枚举u从1到正无穷) ,由于数值可能非常大,输出对1000000007 取模后的余数(即结果mod 1000000007)。

    解题思路:由于ai < 1e6,所以ai的二进制位最多有20位。对每一位来说,假设这一位有xi个1,那么如果要使这一位为1,只需要从xi中选出来奇数个1(假设有k1个),从n-xi中选出来剩余n-k1个零,而这样子的选择方案共有C(xi,1)C(n-xi, k - 1) + C(xi,3)C(n-xi, k - 3) + …… .现在来考虑这样子如何计算结果,假设现在有四个数1 2 3 7, 对应二进制001,010,011,111,从中选k=3个数,那么所有结果总共有

    1^2^3 = 0, 1^2^7 = 4, 1^3^7 = 5, 2^3^7 = 6四个。那么显然答案应当是4+5+6。现在将4 5 6这三个数的二进制展开,得到:

    4 = 0x1 + 0x2 + 1x4

    5 = 1x1 + 0x2 + 1x4

    6 = 0x1 + 2x1 + 1x4

    到这儿大概已经能够发现,只需要将每一位可选的方案数目乘以其对应的2的幂,最后求和即是要求的答案。

    大致过程:扩展gcd求逆元并记录1~1e6的逆元;对于每个xi,使用组合数递推公式C(n,k) = C(n, k - 1) * (n - k + 1) / k 求xi以及n-xi的组合数值,复杂度O(n);最后累加求和即是答案。

    代码:

     1 const int maxn = 1e5 + 5;
     2 ll c[maxn], c1[maxn], inv[maxn];
     3 int n, k;
     4 int ti[20], a1[maxn];
     5 
     6 void ext_gcd(ll a, ll b, ll &d, ll &x, ll &y){
     7     if(b == 0){
     8         d = a; x = 1; y = 0;
     9     }
    10     else{
    11         ext_gcd(b, a % b, d, y, x); 
    12         y -= x * (a / b);
    13     }
    14 }
    15 int modinv(ll a){
    16     ll x, y, d;
    17     ext_gcd(a, -mod, d, x, y);
    18     if(d < 0) x = -x;
    19     return (x + mod) % mod;
    20 }
    21 void getinv(){
    22     for(int i = 2; i <= 1e5; i++)
    23         inv[i] = modinv(i);
    24 }
    25 void getcom(int x){
    26     c[0] = c1[0] = 1; c[1] = x; c1[1] = n - x;
    27     for(int i = 2; i <= x; i++) 
    28         c[i] = c[i - 1] % mod * (x - i + 1) % mod * inv[i] % mod;
    29     for(int i = 2; i <= n - x; i++)
    30         c1[i] = c1[i - 1] % mod * (n - x - i + 1) % mod * inv[i] % mod;
    31 }
    32 void solve(){
    33     getinv();
    34     memset(ti, 0, sizeof(ti));
    35     int mxcnt = 0;
    36     for(int i = 1; i <= n; i++){
    37         int x = a1[i], cnt = 0;
    38         while(x){
    39             ti[cnt++] += (x & 1);
    40             x >>= 1;
    41         }
    42         mxcnt = max(mxcnt, cnt);
    43     }
    44     ll ans = 0;
    45     for(int i = 0; i <= mxcnt; i++){
    46         int x = ti[i], tm = 1 << i;
    47         getcom(x);
    48         for(int i = 1; i <= k; i += 2){
    49             if(k - i > n - x || i > x) continue;
    50             ans = ans + c[i] % mod * c1[k - i] % mod * tm % mod;
    51             ans %= mod;
    52         }
    53     }
    54     printf("%lld
    ", ans);
    55 }
    56 int main(){
    57     scanf("%d %d", &n, &k);
    58     for(int i = 1; i <= n; i++)
    59         scanf("%d", &a1[i]);
    60     solve();
    61 }

    题目:

    10509: xor运算统计

    Time Limit: 5 Sec  Memory Limit: 128 MB
    Submit: 26  Solved: 5
    [Submit][Status][Web Board]

    Description

    给定n个正整数,a1 a2 ... an,从中选取k个数 , ai1 ai2 ai3 ... Aik,其中(1<=i1<i2<i3<...<ik<=n),u=ai1 ^ai2 ^ai3 ^... ^Aik,将异或和为u 的序列(i1,i2,...,ik)的个数记为f(u),求∑(f(u)*u) (枚举u从1到正无穷) ,由于数值可能非常大,输出对1000000007 取模后的余数(即结果mod 1000000007)。

    Input

    第一行两个整数n和k (1<=n,k<=10^5)
    第二行n个整数,表示a1 a2 ... An. (0<=ai<=10^6)

    Output

    输出一行一个整数,表示最后的答案.

    Sample Input

    4 2
    1 1 2 3
    

    Sample Output

    11

    HINT

     

    Source

    JXD

  • 相关阅读:
    mysq 日期相减
    说说时间观与时间管理——北漂18年(71)
    ionic之切换开关
    ionic之单选框
    SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
    14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读
    14.5.2.2 autocommit, Commit, and Rollback
    14.5.2 事务隔离级别
    对于唯一索引使用唯一条件搜索, InnoDB 只锁定找到的index record,不是它之前的区间
    mysql explain 解释
  • 原文地址:https://www.cnblogs.com/bolderic/p/7514101.html
Copyright © 2011-2022 走看看