编程之美初赛第二场 集合

这么晚才写编程之美的解题报告,想记录下自己学习算法的过程。本题出于于2014年编程之美初赛第二场。


题目转述

时间限制: 12000ms
单点时限: 6000ms
内存限制: 256MB

描述

统计满足下列条件的集合对(A, B)的数量:

  • A,B都是{1, 2, …, N}的子集;

  • A,B没有公共的元素;

  • f(A)<= f(B)f(S)定义为S中所有元素的按位异或和。例如, f({}) = 0, f({1, 3}) = 2。

因为答案可能很大,你只需要求出它除以M的余数。


输入

第一行一个整数T (1 ≤ T ≤ 10),表示数据组数。

接下来是T组输入数据,测试数据之间没有空行。

每组数据格式如下:

仅一行,2个整数N和M (1 ≤ M ≤ 108)。


输出

对每组数据,先输出“Case x: ”,然后接一个整数,表示所求的结果。


数据范围

小数据:1 ≤ N ≤ 20

大数据:1 ≤ N < 212


样例输入
1
3 100000000
样例输出
Case 1: 18

解法

      对于集合U={1, 2, ......, N}的任意一个划分{A,B},肯定对应着一个划分{B,A},两者至少有一个满足要求。如果f(A)<f(B),则只有{A,B}满足。如果f(A)>f(B),则{B,A}满足。如果f(A)=f(B),则两个都满足。设所有子集组合{A,B}的数目为X,其中满足f(A)=f(B)的数目为Y,则满足要求的集合对数为X/2+Y/2.

      先考虑计算X,对于任意一个组合{A,B}, 集合U的所有元素均有三个去处即{A, B, 剩余其他元素},所以总数目是3^N。对于这里的组合{A,B}是有顺序的,即{A,B}和{B,A}是两种方案。当{A,B}={B,A}时,即A=B,只能是A和B均为空。所以总的数目X=(3^N-1),排除空集。

      然后计算Y的数目。对于{A,B}满足f(A)=f(B),必有f(AUB)=0。反过来,对于有k个元素的集合R={r1,r2,...,rk},如果f(R)=0,则将R划成两个集合的办法个数为所以,只需要找出所有满足f(R)=0的子集。下面采用动态规划来计算满足f(AUB)=0的方案数。

      定义dp[i][j]表示前i个数分配好的情形下,两个集合异或值为j的方案数。则满足f(A)=f(B)的方案数即为dp[N][0]。有状态转移方程如下:

      dp[i+1][j] = (dp[i][j] + 2 * dp[i][j^(i+1)])

理解为,前面i+1个数,异或结果为j的方案数,可以分成两类:一是不选择i+1,即dp[i][j]。二是选择i+1,将i+1加入到异或结果为j^(i+1)的两个集合中任意一个,都会得到一个新方案,异或结果为j.

      初始状态:dp[0][0]=1,即两个均为空集的方案。dp[0][j]=0, j > 0。

      dp[N][0]的结果中,{A,B}和{B,A}会被计算成两种,但空集方案仅一种,即dp[0][0]=1。排除空集方案,Y=dp[N][0]-1。所以,总的方案数NUM=X/2+Y/2+1(空集)=(3^N+dp[N][0])/2。

      在N较大的情况下,NUM要对M求余。求余必须渗透于计算过程中的每一步,即3^N和dp[N][0]的计算过程。有一个小麻烦,就是除以2如何处理。

      先证明除以2的等价计算方法。假设现在要求x/2对M的余数,首先计算x对2M的余数,不妨设为r,令x=2Mk+r(k是整数)。于是x/2=Mk+r/2。x/2对M的余数就是r/2,且不论x的奇偶性。

      所以,该问题简化为,在计算3^N+dp[N][0]的过程中,对2M求余。最后余数除以2即得NUM对M的余数,可以记为(3^N+dp[N][0])%(2M)/2。

      本文分析到此结束,欢迎大家探讨!


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值