2014編程之美初賽2場第3題

題目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;

}

}


更多資訊,請點擊:華萬微信圖文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章