题目3 : 集合

时间限制: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



解题思路:

   用了暴力求解,性能真的令人担忧,N=10及以下可以畅快运行,以上的话就不可以了,解题仅供参考。不建议这么做。

   求出N个数所有的子集。求子集的方法是通过,遍历从0-(2^n-1),变成二进制的形式,0为该位置的数不出现,1为该位置的数出现。

   求出每个子集对应的异或和。

   两次循环遍历,寻找符合条件的数组,用Count计算。

   最后取模输出答案。

java代码:

package ruming.wei;

import java.util.HashMap;

import java.util.HashSet;

import java.util.Iterator;

import java.util.Map;

import java.util.Scanner;


public class chusai2_q3 {

public static void main(String[] args) {

chusai2_q3 app=new chusai2_q3();

       Scanner in = new Scanner(System.in);

       String input=in.nextLine();

       int T=Integer.valueOf(input);

       for(int i=0;i<T;i++){

            input=in.nextLine();

            int N,M;

            N=Integer.parseInt(input.split(" ")[0]);

            M=Integer.parseInt(input.split(" ")[1]);

            HashMap<HashSet<String>, Integer> all=app.createAll(N);

            Iterator iterator1=all.entrySet().iterator();

            int count=0;

            while(iterator1.hasNext()){

Map.Entry entry1=(Map.Entry)iterator1.next();

Iterator iterator2=all.entrySet().iterator();

HashSet<String> setA=(HashSet<String>) entry1.getKey();

while(iterator2.hasNext()){

Map.Entry entry2=(Map.Entry)iterator2.next();

 HashSet<String> setB=(HashSet<String>) entry2.getKey();

boolean flag=true;

for(String aString:setA){

for(String bString:setB)

{

if(!aString.equals("null")&&aString.equals(bString))

{

flag=false;

break;

}

}

}

 int Axor=(Integer)entry1.getValue();

 int Bxor=(Integer)entry2.getValue();            

 if(flag&&Axor<=Bxor)

 {

 count++;

 System.out.println("A:"+setA+"-->"+Axor+"    "+"B:"+setB+"-->"+Bxor);

 }

}  

//System.out.println(entry1.getKey()+"-->"+entry1.getValue());      

            }

System.out.println("Case "+(i+1)+": "+count%M);

}

}

private HashMap<HashSet<String>, Integer>  createAll(int N){

int count=2<<(N-1);

HashMap<HashSet<String>, Integer> all= new HashMap<HashSet<String>, Integer>();

for(int i=0;i<count;i++){

String str=String.valueOf(Integer.toBinaryString(i));

while(str.length()<N)

str ="0"+str;//以‘0’向前填充字符串为N个字符

if(i==0)

{

HashSet<String> set=new HashSet<String>();

set.add("null");

all.put(set, 0);

}

else {

String change="";

HashSet<String> set=new HashSet<String>();

for(int j=0;j<str.length();j++){

char cc=str.charAt(j);

if(cc=='1')

{

change +=String.valueOf(j+1)+" ";

set.add(String.valueOf(String.valueOf(j+1)));

}

}

all.put(set, f(change));

}

}

return all;

}

private int f(String change) {

String[] subs=change.split(" ");

int xor=Integer.parseInt(subs[0]);

for(int i=1;i<subs.length;i++){

xor ^=Integer.parseInt(subs[i]);

}

return xor;

}

}


更多资讯,请点击:华万微信图文