嘴巴AC选手 之 [TopCoder12004]-容斥计数

说在前面

怕自己忘掉了…
赶紧写下来记录me的愚蠢


题目

TC12004传送门
Vjudge–>TC12004传送门

题目大意

给出N个数字,N不超过50,数字大小不超过1048575
现在要将这个N个数字染上红色或者黑色,要求相同颜色的数字与起来的和相等,询问染色方案数
(注意:对于两个数A,B,A红B黑 和 A黑B红 是不同的染色方案)

输入输出格式

你需要写一个class,这个class大概长这样:
函数调用是允许的

class SetAndSet {
    public :
    long long countandset ( vector < int > A )   {
        int n = A.size ( )  ;
        long long ans = 0 ;
        // here is your code 
        return ans ;
    }
} ;

数组将会以vector传参的方式给出,函数返回值作为答案


解法

对每一个二进制位分开考虑
假设对于第k个二进制位:
如果所有数的第k位上全为0或全为1,那么显然无论怎么分组,两组的第k位都相等
如果不全为1,那么假设第k位上为0的数字集合为S。如果整个S都被染上了相同的颜色,显然第k位就不相等了。

那么可以考虑容斥,最终答案 = 总方案数 - 有一位不相等的 + 有两位不相等的….
在计算有多位不相等的时候,如果这两位对应的集合 S1,S2 S 1 , S 2 有交集,那么 S1S2 S 1 ⋃ S 2 的所有元素颜色必须一致。如果没有交集,那么 S1 S 1 , S2 S 2 的颜色只需要满足集合内部相同即可,而不需要保持颜色一致(me真是蠢到一种境界,写的时候直接钦定 S1 S 1 S2 S 2 颜色一致了,WA了两个小时才发现问题…)。

所以最终实现的时候,可以采用dfs+并查集维护连通块个数。


下面是自带大常数的代码

什么?代码?不存在的~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值