试题 C:数组分割
[问题描述]
小蓝有一个长度为N的数组A=[A0,A1,...,AN-1]。现在小蓝想要从A对应的数组下标所构成的集合I={0,1,2,...,N-1}中找出一个子集R,那么R1在I中的补集为R2。记S1=∑reAr,S2=∑reAr,我们要求S1和S2均为偶数,请问在这种情况下共有多少种不同的R1。当R1或R₂为空集时我们将 S或S₂视为0。
[输入格式]
第一行一个整数T,表示有T组数据。
接下来输入T组数据,每组数据包含两行:
第一行一个整数N,表示数组 A 的长度;
第二行输入N个整数从左至右依次为Ao,A1,...,AN-1,相邻元素之间用空格分隔。
[输出格式]
对于每组数据,输出一行,包含一个整数表示答案,答案可能会很大,你需要将答案对1000000007进行取模后输出。
[样例输入]
22
[样例输出]
4
0
[样例说明]
对于第一组数据,答案为4。(注意:大括号内的数字表示元素在数组中的下标。)
R1 = {0},R2 ={1}; 此时 S1= Ao=6 为偶数,S2=A1=6为偶数。
R1 ={1},R2 = {0}; 此时 S1=A1=6 为偶数,S2=A0=6为偶数。
R1 = {0,1},R2 ={}; 此时 S1=A +A1=12 为偶数,S2=0为偶数。
R1 = {},R2 ={0,1};此时S1=0为偶数, S2 = A0 +A1=12为偶数。
对于第二组数据,无论怎么选择,都不满足条件,所以答案为0。
主要是对数学排列组合的理解
偶数+偶数=偶数
奇数+奇数=偶数(可以以理解为偶数个奇数相加)
A中偶数分为一组A1,元素个数为L,奇数分为一组A2,元素个数为J。(J一定为偶数,因为如果A中有奇数个奇数的话,由奇数+奇数=偶数(可以以理解为偶数个奇数相加)可知,R1+R2无法凑成偶数)
接下来考虑R1有多少种排列组合
R1中的元素都是偶数,因此可以随便取,都能保证S1都是偶数,因此有取和不取两种情况,因此R1中的元素有2的L次方种取法。
R2中的元素由于都是奇数,由奇数+奇数=偶数(可以以理解为偶数个奇数相加),因此R2中的元素一次要取偶数个。
C(0,J)在J个元素中任取0个;
C(2,J)在J个元素中任取2个;
C(2n,J)在J个元素中任取2n个;
R2的取法=C(0,J)+C(2,J)+C(2n,J)+C(J,J)
R2中的元素有2的J-1次方种取法。
因此一共有2的L次方*2的J-1次方种取法。
代码
package cc;
import java.util.Scanner;
public class hh {
public static void main(String[]arga) {
int mod=1000000007;
Scanner scanner=new Scanner(System.in);
System.out.println("请输入有T组数据");
int t=scanner.nextInt();
while(t>0) {
System.out.println("数组 A 的长度N为");
int n=scanner.nextInt();
int[] arr=new int[n];
System.out.println("输入N个整数");
int j=0;//奇数
int l=0;//偶数
for(int i=0;i<arr.length;i++) {
arr[i]=scanner.nextInt();
if(arr[i]%2!=0)j++;
else l++;
}
if(j%2!=0)System.out.println("0");
else {
int count=(int) (Math.pow(2,l)*Math.pow(2, j-1))%mod;
System.out.println(count);
}
t--;
}
}
}