2014编程之美初赛第二场1003 集合
2014-04-21 18:19
288 查看
题目链接:集合
时间限制:12000ms
单点时限:6000ms
内存限制:256MB
A,B都是{1,
2, …, N}的子集;
A,B没有公共的元素;
f(A)<= f(B)。f(S)定义为S中所有元素的按位异或和。例如,
f({}) = 0, f({1, 3}) = 2。
因为答案可能很大,你只需要求出它除以M的余数。
接下来是T组输入数据,测试数据之间没有空行。
每组数据格式如下:
仅一行,2个整数N和M (1 ≤ M ≤ 108)。
”,然后接一个整数,表示所求的结果。
大数据:1 ≤ N < 212
样例输入
样例输出
本质:
组合数学+DP
思路:
首先,所有的分组情况是3^n(每个元素可以放在第一个集合,也可以放在第二个集合,也可以抛弃),对于每一种情况,把异或值小的放在左边,异或值大的放在右边,都能满足情况,那么有(3^n)/2种情况,但是左右两边异或值相同的时候可以计算两次,所以还要加上相等情况数的一半,左右两边异或相等的时候,那么左右两个集合的并集的异或值为0,那么我们需要知道1~n中有多少组数异或为0的情况,并且如果找到一组k个数字异或为0,那么现在将对这组数字进行分配:把0个元素分配到左边的集合:C(k,0)、把1个元素分配到左边的集合:C(k,1)...把k个元素分配到左边的集合:C(k,k),总共的情况数是2^k,那么我们计算的时候就可以用DP进行递推了
dp[i][j]代表前i个数分配好了,两个集合的异或值为j的方案数
有转移:
dp[i+1][j]+=dp[i][j];
dp[i+1][j^(i+1)]+=dp[i][j]*2;//多一个数,2^k中k+1,那么方案数要乘以2
所以最后的答案就等于(3^n+dp
[0])/2
由于过程要求余m,但是最后结果的时候要除以2,从Logic_IU得知了一个比较好的处理办法,求余2m即可,妙哉
时间限制: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
本质:
组合数学+DP
思路:
首先,所有的分组情况是3^n(每个元素可以放在第一个集合,也可以放在第二个集合,也可以抛弃),对于每一种情况,把异或值小的放在左边,异或值大的放在右边,都能满足情况,那么有(3^n)/2种情况,但是左右两边异或值相同的时候可以计算两次,所以还要加上相等情况数的一半,左右两边异或相等的时候,那么左右两个集合的并集的异或值为0,那么我们需要知道1~n中有多少组数异或为0的情况,并且如果找到一组k个数字异或为0,那么现在将对这组数字进行分配:把0个元素分配到左边的集合:C(k,0)、把1个元素分配到左边的集合:C(k,1)...把k个元素分配到左边的集合:C(k,k),总共的情况数是2^k,那么我们计算的时候就可以用DP进行递推了
dp[i][j]代表前i个数分配好了,两个集合的异或值为j的方案数
有转移:
dp[i+1][j]+=dp[i][j];
dp[i+1][j^(i+1)]+=dp[i][j]*2;//多一个数,2^k中k+1,那么方案数要乘以2
所以最后的答案就等于(3^n+dp
[0])/2
由于过程要求余m,但是最后结果的时候要除以2,从Logic_IU得知了一个比较好的处理办法,求余2m即可,妙哉
#include<stdio.h> #include<string.h> long long int dp[4500][4500];//dp[i][j]代表前i个数分配好了,异或值为j的方案数 long long int num[20]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095}; int main() { long long int I,T,n,MOD,i,j,ans,m,MOD2,t; scanf("%lld",&T); for(I=1;I<=T;I++) { scanf("%lld%lld",&n,&MOD); MOD2=MOD*2; ans=1; for(i=1;i<=n;i++) ans=(ans*3)%MOD2; for(i=1;i<=12;i++)//找到1~n异或的上限 if(n<=num[i]) break; m=num[i]; memset(dp,0,sizeof(dp)); dp[0][0]=1; for(i=0;i<n;i++) for(j=0;j<=m;j++) { t=j^(i+1); dp[i+1][j]=(dp[i+1][j]+dp[i][j])%MOD; dp[i+1][t]=(dp[i+1][t]+dp[i][j]*2)%MOD; } ans=(ans+dp [0])%MOD2; ans/=2; ans%=MOD; printf("Case %lld: %lld\n",I,ans); } return 0; }
相关文章推荐
- 微软2014编程之美初赛第二场——题目3 : 集合
- 2014编程之美初赛第二场
- 编程之美初赛第二场 集合
- 微软2014编程之美初赛第二场——题目2 : 字符串压缩
- 2014编程之美初赛第二场
- 微软2014编程之美初赛第二场——题目2 : 字符串压缩
- 2014编程之美初赛第二场
- 2014编程之美初赛第二场—神奇的数列(2014.4.20)
- 编程之美初赛第二场 集合
- 编程之美初赛第二场 集合
- (3)2014微软编程之美初赛第二场赛题
- 2014多校1(1003)hdu4863
- hdu 4962 Closed Paths 计算几何 2014 Multi-University Training Contest 9-1003
- 2014多校5(1003)hdu4913(线段树区间操作)
- 2014 百度之星 1003 题解 Xor Sum
- 2014上海网络预选赛1003(树链剖分)HDU5044
- hdu 6047: Maximum Sequence (2017 多校第二场 1003)【贪心】
- 编程之美初赛第二场 神奇的数列 + 字符串压缩
- 最新版华为交换机配置命令集合(2014最新)
- 2014多校第七场1003 || HDU 4937 Lucky Number