题目链接:

https://acm.ecnu.edu.cn/problem/3300/

题目大意:

给n个数,求在n个数中选两个数(可重复),使得这两个数的组合数是奇数,求总共有多少种取法。

解题思路:

组合数Cnm奇偶性判断:

n & m == m 成立则组合数为奇数

一开始没什么的思路,直接暴力超时,后来看到Lucas定理,发现上面那个式子的本质就是从这里推导出来的。

Lucas定理:

组合数判断奇数的话就是转化成上述定理中p = 2

是否为1,利用Lucas定理,先把化为二进制,这样它们都是01序列了。我们又知道

。这样中为0的地方对应的中的位置只有一种可能,那就是0

这样n&m = m的本质就是二进制中n对应的0得地方,m也对应为0。

然而,就是这个本质,就可以解这道题目

有位大佬一句话点醒了我,n&m = m说明m是n的子集。

对的,用二进制表示子集的时候,就是这样,m是n的子集,等价于n为0的位置m一定为0,n为1

的位置,m可以为1,可以为0。

然后对于每个n,求出它的子集的数目即可。

对于求子集,大佬教的方法是高维前缀和,代码很简单,就三行,和状态压缩DP一样。

 for(int i = ; i < m; i++)
{
for(int j = ; j < (<<m); j++)
{
if(j & (<<i))
sum[j] += sum[j ^ (<<i)];
}
}

举个例子,sum[0101] = sum[0101] + sum[0100] + sum[0001] + sum[0000]

sum[i]就表示i二进制的所有子集的权值之和

对于组合数n & m == m  m是n的子集,

先统计每个数出现的次数,然后对于每个数,统计它的子集的个数即可,最后答案相加。

 #include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + ;
typedef long long ll;
ll a[maxn], sum[maxn];
int main()
{
int T, n, x;
cin >> T;
while(T--)
{
scanf("%d", &n);
memset(a, , sizeof(a));
memset(sum, , sizeof(sum));
for(int i = ; i < n; i++)
{
scanf("%d", &a[i]);
sum[a[i]]++;
}
int m = ;
for(int i = ; i < m; i++)
{
for(int j = ; j < (<<m); j++)
{
if(j & (<<i))
sum[j] += sum[j ^ (<<i)];
}
}
ll ans = ;
for(int i = ; i < n; i++)
ans += sum[a[i]];
cout<<ans<<endl;
}
return ;
}

EOJ-3300 奇数统计(高维前缀和)的更多相关文章

  1. HDU.5765.Bonds(DP 高维前缀和)

    题目链接 \(Description\) 给定一张\(n\)个点\(m\)条边的无向图.定义割集\(E\)为去掉\(E\)后使得图不连通的边集.定义一个bond为一个极小割集(即bond中边的任意一个 ...

  2. 【洛谷5643】[PKUWC2018] 随机游走(Min-Max容斥+待定系数法+高维前缀和)

    点此看题面 大致题意: 从一个给定点出发,在一棵树上随机游走,对于相邻的每个点均有\(\frac 1{deg}\)的概率前往.多组询问,每次给出一个点集,求期望经过多少步能够访问过点集内所有点至少一次 ...

  3. BZOJ.5092.[Lydsy1711月赛]分割序列(高维前缀和)

    题目链接 \(Description\) \(Solution\) 首先处理\(a_i\)的前缀异或和\(s_i\).那么在对于序列\(a_1,...,a_n\),在\(i\)位置处分开的价值为:\( ...

  4. SPOJ.TLE - Time Limit Exceeded(DP 高维前缀和)

    题目链接 \(Description\) 给定长为\(n\)的数组\(c_i\)和\(m\),求长为\(n\)的序列\(a_i\)个数,满足:\(c_i\not\mid a_i,\quad a_i\& ...

  5. LOJ2542 PKUWC2018 随机游走 min-max容斥、树上高斯消元、高维前缀和、期望

    传送门 那么除了D1T3,PKUWC2018就更完了(斗地主这种全场0分的题怎么会做啊) 发现我们要求的是所有点中到达时间的最大值的期望,\(n\)又很小,考虑min-max容斥 那么我们要求从\(x ...

  6. Luogu3175 HAOI2015 按位或 min-max容斥、高维前缀和、期望

    传送门 套路题 看到\(n \leq 20\),又看到我们求的是最后出现的位置出现的时间的期望,也就是集合中最大值的期望,考虑min-max容斥. 由\(E(max(S)) = \sum\limits ...

  7. BZOJ5092:[Lydsy1711月赛]分割序列(贪心,高维前缀和)

    Description 对于一个长度为n的非负整数序列b_1,b_2,...,b_n,定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b_2 xor...xor b ...

  8. HihoCoder - 1496:寻找最大值(高维前缀和||手动求子集)

    描述 给定N个数A1, A2, A3, ... AN,小Ho想从中找到两个数Ai和Aj(i ≠ j)使得乘积Ai × Aj × (Ai AND Aj)最大.其中AND是按位与操作. 小Ho当然知道怎么 ...

  9. BZOJ:5092 [Lydsy1711月赛]分割序列(贪心&高维前缀和)

    Description 对于一个长度为n的非负整数序列b_1,b_2,...,b_n,定义这个序列的能量为:f(b)=max{i=0,1,...,n}((b_1 xor b _2 xor...xor ...

随机推荐

  1. poj 2105 IP Address

    IP Address Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18951   Accepted: 10939 Desc ...

  2. 第七章使用java实现面向对象- 多线程

    一.Thread类和Runnable接口 1.在java.lang包中定义了Runnable接口和Thread类. Runnable接口中只定义了一个方法,它的格式为: public abstract ...

  3. Eclipse 工具栏无法移动的解决办法

    升级到Juno后发现工具栏有些乱 而且无法拖动,试了下http://blog.csdn.net/cxx504659987/article/details/38532599的方法 发现配置文件里没有文中 ...

  4. Sequence contains no elements : LINQ error

    1.错误意思: 出现错误的原因是:你要从一个null中取的数据. 2.错误的处理 1,使用FirstOrDefault() 来代替 First() 2.使用SingleOrDefault 来代替 Si ...

  5. EasyPusher推流类库的.NET调用说明

    EasyPusher推流类库的.NET调用说明 以下内容基于在使用EasyPusher过程中遇到的问题,以及相应的注意事项.本文主要是基于对C++类库的二次封装(便于调试发现问题)以供C#调用以及对一 ...

  6. Spring 中任意位置获取 session 和 request

    在web.xml中添加监听: <listener> <listener-class>org.springframework.web.context.ContextLoaderL ...

  7. Navicat 连接MySQL 8.0.11 出现2059错误

    错误 使用Navicat Premium 连接MySQL时出现如下错误: 原因 mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是cach ...

  8. Jmail发送邮件工具类

    好久没更新博客了,实在是拖延症严重啊,好可怕,先更新个工具类吧,之前写的发送邮件的小工具,话不多说上代码 import lombok.extern.slf4j.Slf4j; import java.u ...

  9. thinkphp注册并写入数据到数据库中

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. Linux基础之-Bash命令优先级

    一. Bash简介 命令解释器,也就是 Bourne Again Shell,起源于shell.shell俗称壳,它是指UNIX系统下的一个命令解析器:主要用于用户和系统的交互.UNIX系统上有很多种 ...